Teaching materials

\(~\)

‘hungry forager’ primer:

‘satiated forager’ primer:

Pigeon footage is available on the github page associated with this report. It can be accessed here: https://github.com/tomkeaney/Biased_pigeons by downloading the pigeon_video.mp4 file.

\(~\)

Load packages and the data

library(tidyverse) # tidy style coding
library(brms) # Bayesian models
library(loo) # for information criteria
library(tidybayes) # Bayesian aesthetics
library(MetBrewer) # colours
library(kableExtra) # tables
library(patchwork) # putting plots together
library(DT) # for search- and saveable tables
library(pander) # for simpler tables
library(png) # to load images
library(grid) # to plot images
library(ggdag) # to draw dags
data <- read_csv("data/pigeon_data.csv") %>% 
  mutate(Student_ID = as.factor(Student_ID),
         Year = as.factor(Year),
         Foraging_prop = (Foraging_percentage / 100)) %>%
  filter(Year %in% c("2021", "2022", "2023"),
         Foraging_percentage != "NA",
         Primer_understood != "NA") %>%
  filter(Student_ID != "60" & Student_ID != "68" & Student_ID != "70" & Student_ID != "72") %>% # remove students that completed the task multiple times
  #Student_ID %in% c("60", "68", "70", "72")) %>% 
  select(-c(First_name, Surname, Peck_mean)) %>%  # remove names when ready
  left_join(
    read_csv("data/gender_data.csv") %>% 
      mutate(Student_ID = as.factor(Student_ID))
  ) %>% 
  rename(Observer_ID = Student_ID) %>% 
  select(Observer_ID, Year, Gender, everything())

data_peck <- 
  data %>%
  filter(Peck_rate_2 != "NA") %>% 
  pivot_longer(cols = Peck_rate_1:Peck_rate_2, names_to = "Trial",
               values_to = "Peck_rate")
  
# Create a function to build HTML searchable tables

my_data_table <- function(df){
  datatable(
    df, rownames=FALSE,
    autoHideNavigation = TRUE,
    extensions = c("Scroller",  "Buttons"),
    options = list(
      dom = 'Bfrtip',
      deferRender=TRUE,
      scrollX=TRUE, scrollY=400,
      scrollCollapse=TRUE,
      buttons =
        list('pageLength', 'colvis', 'csv', list(
          extend = 'pdf',
          pageSize = 'A4',
          orientation = 'landscape',
          filename = 'full_dataset')),
      pageLength = 78
    )
  )
}

my_data_table(data)

Column explanations

Observer_ID: unique, anonymised identifier for each observer.

Year: year that the experiment was conducted.

Gender: upon enrollment at The University of Melbourne, students are asked to indicate their title. We identified women as observers that answered “Miss” or “Ms” and Men as those who that answered “Mr”. Those with entirely missing entries were coded as “NA”.

Bias_treatment: the primer the observer received, where ‘satiated’ indicates that the observers were provided information prior to a trial that suggested pigeons were fell fed, whereas ‘hungry’ indicated that the pigeons were in poor condition and hungry.

Expectation: we asked the observers to indicate whether they thought the pigeons would be hungry or satiated. We included this question to test whether observers were appropriately primed by their bias treatment.

Primer_understood: did the observer’s expectation match the primer they received?

Foraging_percentage: the percentage of pigeons that observers estimated to be foraging over a 15 second period, while observing a large flock.

Peck_rate_1: the number of times a single chosen pigeon pecked the ground over a 15 second period.

Peck_rate_2: the number of times a second chosen pigeon pecked the ground over a 15 second period.

Foraging_prop: proportion of pigeons estimated to be foraging

\(~\)

Question 1: is estimation of foraging percentage affected by bias manipulations?

\(~\)

Exploring allocation versus expectation 1

\(~\)

We find that 22 of the 78 observers indicated a feeding motivation expectation opposite to that implied by the primer they were allocated.

This suggests that Expectation may be a better predictor of foraging estimation than allocated Bias_treatment. The relationship between these and all other variables that we expect to play a role in this system are depicted in Figure 1.

We explicitly assess the effect of treatment and expectation by fitting two models:

  1. a model with allocated primer (Bias_treatment) as the predictor variable

  2. a model with indicated hunger expectation (Expectation) as the predictor variable

\(~\)

\(~\)

Model 1: allocated primer

# First let's model the effect of bias treatment on foraging estimation 

foraging_model_treatment <- brm(Foraging_prop ~ 0 + Bias_treatment,
                                     data = data, family = Beta,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = phi)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.8, max_treedepth = 10),
                                     seed = 1, file = "fits/foraging_model_treatment")

foraging_model_treatment <- add_criterion(foraging_model_treatment, criterion = "loo", file = "fits/foraging_model_treatment")

foraging_model_treatment
##  Family: beta 
##   Links: mu = logit; phi = identity 
## Formula: Foraging_prop ~ 0 + Bias_treatment 
##    Data: data (Number of observations: 78) 
##   Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
##          total post-warmup draws = 16000
## 
## Population-Level Effects: 
##                        Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Bias_treatmentHungry      -0.47      0.14    -0.74    -0.20 1.00    14927
## Bias_treatmentSatiated    -0.47      0.15    -0.76    -0.17 1.00    14749
##                        Tail_ESS
## Bias_treatmentHungry      12186
## Bias_treatmentSatiated    11819
## 
## Family Specific Parameters: 
##     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## phi     4.21      0.61     3.11     5.48 1.00    13695    12202
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
foraging_model_treatment_gender <- brm(Foraging_prop ~ 0 + Gender * Bias_treatment,
                                     data = data, family = Beta,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = phi)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.8, max_treedepth = 10),
                                     seed = 1, file = "fits/foraging_model_treatment_gender")

Table S1. Posterior estimates of the percentage of pigeon feeding rate, split by the primer observers were allocated.

new_data <- tibble(Bias_treatment = c("Hungry", "Satiated"))

new_data %>% 
  left_join(data %>% group_by(Bias_treatment) %>% summarise(`n observers` = n())) %>% 
  cbind(fitted(foraging_model_treatment, newdata = new_data, summary = T) %>% 
          as_tibble() %>% 
          mutate(across(1:4, ~ .x *100),
                 across(1:4, round, 2))) %>% 
  rename("Estimated proportion foraging" = Estimate,
         "Bias treatment" = Bias_treatment) %>% 
  pander(split.cell = 20, split.table = Inf)
Bias treatment n observers Estimated proportion foraging Est.Error Q2.5 Q97.5
Hungry 42 38.47 3.25 32.24 44.99
Satiated 36 38.59 3.51 31.85 45.65

Model 2: indicated expectation

# fit the same model, except using participant expectation rather than allocated bias treatment

foraging_model_expectation <- brm(Foraging_prop ~ 0 + Expectation,
                                     data = data, family = Beta,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = phi)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.8, max_treedepth = 10),
                                     seed = 1, file = "fits/foraging_model_expectation")

foraging_model_expectation <- add_criterion(foraging_model_expectation, criterion = "loo", file = "fits/foraging_model_expectation")

foraging_model_expectation
##  Family: beta 
##   Links: mu = logit; phi = identity 
## Formula: Foraging_prop ~ 0 + Expectation 
##    Data: data (Number of observations: 78) 
##   Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
##          total post-warmup draws = 16000
## 
## Population-Level Effects: 
##                     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## ExpectationHungry      -0.40      0.13    -0.66    -0.14 1.00    15078    12139
## ExpectationSatiated    -0.56      0.15    -0.87    -0.26 1.00    15944    12233
## 
## Family Specific Parameters: 
##     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## phi     4.25      0.62     3.12     5.55 1.00    16348    12206
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
foraging_model_expectation_gender <- brm(Foraging_prop ~ 0 + Gender * Expectation,
                                     data = data, family = Beta,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = phi)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.8, max_treedepth = 10),
                                     seed = 1, file = "fits/foraging_model_expectation_gender")

Table S2. Posterior estimates of the percentage of pigeons foraging, split by the actual expectation of observers.

new_data_2 <- tibble(Expectation = c("Hungry", "Satiated"))

new_data_2 %>% 
   left_join(data %>% group_by(Expectation) %>% summarise(`n observers` = n())) %>% 
  cbind(fitted(foraging_model_expectation, newdata = new_data_2, summary = T) %>% 
          as_tibble() %>% 
          mutate(across(1:4, ~ .x *100),
                 across(1:4, round, 2))) %>%  
  rename("Estimated proportion foraging" = Estimate,
         "Indicated expectation" = Expectation) %>% 
  pander(split.cell = 20, split.table = Inf)
Indicated expectation n observers Estimated proportion foraging Est.Error Q2.5 Q97.5
Hungry 44 40.2 3.19 34.08 46.62
Satiated 34 36.38 3.56 29.61 43.56

\(~\)

Build Figure 1a-d

\(~\)

Get posterior means and difference contrasts

# treatment model

draws_treatment <-
  as_draws_df(foraging_model_treatment) %>% 
  mutate(Hungry = inv_logit_scaled(b_Bias_treatmentHungry) *100,
         Satiated = inv_logit_scaled(b_Bias_treatmentSatiated)*100,
         diff_contrast = (Hungry - Satiated)) %>% 
  select(Hungry, Satiated, diff_contrast) %>% 
  pivot_longer(names_to = "Treatment", values_to = "Posterior_estimate", cols = 1:3) %>% 
  mutate(Predictor = "Allocated primer")

p2 <- 
  draws_treatment %>% 
  filter(Treatment != "diff_contrast") %>% 
  ggplot(aes(x = Treatment, y = Posterior_estimate)) + 
  stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5) +
  scale_fill_manual(values = met.brewer("Hiroshige", 2)) +
  coord_flip(ylim = c(25, 55)) +
  #geom_vline(xintercept = 0, linetype = 2) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab("Allocated primer") +
  ylab("Estimated % pigeons foraging") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        text = element_text(size = 14))

p3 <-
  draws_treatment %>% 
  filter(Treatment == "diff_contrast") %>% 
  ggplot(aes(y = Posterior_estimate)) + 
   stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5, scale =0.5) +
  scale_fill_manual(values = met.brewer("Hiroshige")[4]) +
  coord_flip(ylim = c(-20, 20)) +
  geom_hline(yintercept = 0, linetype = 2, linewidth = 0.75) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab(NULL) +
  ylab("Hungry - Satiated difference\ncontrast (% points)") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        text = element_text(size = 14))

# expectation model

draws_expectation <-
  as_draws_df(foraging_model_expectation) %>% 
  mutate(Hungry = inv_logit_scaled(b_ExpectationHungry) *100,
         Satiated = inv_logit_scaled(b_ExpectationSatiated)*100,
         diff_contrast = (Hungry - Satiated)) %>% 
  select(Hungry, Satiated, diff_contrast) %>% 
  pivot_longer(names_to = "Treatment", values_to = "Posterior_estimate", cols = 1:3) %>% 
  mutate(Predictor = "Indicated expectation")

p4 <-
  draws_expectation %>% 
  filter(Treatment != "diff_contrast") %>% 
  ggplot(aes(x = Treatment, y = Posterior_estimate)) + 
   stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5) +
  scale_fill_manual(values = met.brewer("Hiroshige", 2)) +
  coord_flip(ylim = c(25, 55)) +
  #geom_vline(xintercept = 0, linetype = 2) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab("Indicated expectation") +
  ylab("Estimated % pigeons foraging") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        text = element_text(size = 14))

p5 <-
  draws_expectation %>% 
  filter(Treatment == "diff_contrast") %>% 
  ggplot(aes(y = Posterior_estimate)) + 
    stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5, scale =0.5) +
  scale_fill_manual(values = met.brewer("Hiroshige")[4]) +
  coord_flip(ylim = c(-20, 20)) +
  geom_hline(yintercept = 0, linetype = 2, linewidth = 0.75) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab(NULL) +
  ylab("Hungry - Satiated difference\ncontrast (% points)") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        text = element_text(size = 14))

\(~\)

Question 2: is estimation of feeding rate affected by bias manipulations?

\(~\)

We asked observers to count the number of pecks of the ground that a selected pigeon made over a 1 minute period. We use the number of pecks that occur as a measure of feeding rate.

We first estimated a baseline peck rate by observing 35 pigeons. To select the pigeons we observed, we split a still image of the foraging video (taken at time zero) into a 43 x 21 cell grid. From the 122 cells that contained pigeons, 40 were chosen by random number generation (see code chunk below). In the event that multiple pigeons were present in the cell, we selected the most prominent to observe. Five observations were discarded - three due to overlap of the same pigeon between cells that were selected by the random number generator, and two more as the pigeons left the field of view during the video and could no longer be tracked.

# curly brackets run all lines included within them

{set.seed(1) # so that sample produces a reproducible sequence 
  sample(1:122, 40, replace = FALSE)}
##  [1] 121  68  39   1  34  87  43  14  82  59  51  97  85  21 106  54  74   7  73
## [20]  79 110  37  89 101 118 100  44 103  33  84  35  70 108  42  38  20  28 117
## [39]  96  91

The selected pigeons for baseline observation are shown in the image below

img <- readPNG("pigeon_selection.png")
 grid.raster(img)

\(~\)

Estimating baseline feeding rate

\(~\)

Load in the data

baseline_data <- read_csv("data/baseline_peck_data.csv") %>% 
  select(1:5) %>%  # remove the comments column
  pivot_longer(cols = 4:5, names_to = "Observation", values_to = "Peck_rate") %>% 
  mutate(ID = as.factor(ID),
         Observation = str_remove(Observation, "Peck_count_")) %>% 
  rename(Pigeon_ID = ID) %>% 
  filter(!is.na(Peck_rate))

my_data_table <- function(df){
  datatable(
    df, rownames=FALSE,
    autoHideNavigation = TRUE,
    extensions = c("Scroller",  "Buttons"),
    options = list(
      dom = 'Bfrtip',
      deferRender=TRUE,
      scrollX=TRUE, scrollY=400,
      scrollCollapse=TRUE,
      buttons =
        list('pageLength', 'colvis', 'csv', list(
          extend = 'pdf',
          pageSize = 'A4',
          orientation = 'landscape',
          filename = 'baseline_dataset')),
      pageLength = 78
    )
  )
}


my_data_table(baseline_data)
  • X and Y represent grid coordinates.

  • Pigeon_ID identifies a specific pigeon

  • Observation indicates whether this was the first or second scoring for a single pigeon. We scored each pigeon twice as distant pigeons were difficult to observe and to ensure that the correct pigeon was tracked throughout the minute of observation.

  • Peck_rate is the number of times the ground was pecked over a minute of observation.

\(~\)

Fit a simple model to estimate median peck rate

baseline_peck_model_zi <-
  brm(Peck_rate ~ 1 + (1|Pigeon_ID),
      family = zero_inflated_negbinomial(), data = baseline_data,
      prior = c( prior(normal(0, 1.5), class = Intercept),
                 prior(exponential(1), class = sd),
                 prior(exponential(1), class = shape),
                 prior(exponential(1), class = zi)),
      chains = 4, cores = 4, warmup = 2000, iter = 6000,
      file = "fits/baseline_peck_model")

# wrangle the output

baseline_peck_predictions <-
  baseline_peck_model_zi %>% 
  as_draws_df() %>% 
  mutate(Baseline_estimate = exp(b_Intercept),
         peck_rate_sd = exp(sd_Pigeon_ID__Intercept)) %>% 
  select(Baseline_estimate, peck_rate_sd)

baseline_data %>% 
  distinct(Pigeon_ID) %>% 
  summarise(`n pigeons observed` = length(Pigeon_ID)) %>%
  bind_cols(
fitted(baseline_peck_model_zi, summary = T, re_formula = NA) %>% 
          as_tibble() %>%
          distinct(Estimate, .keep_all = T) %>% 
          mutate(across(1:4, round, 2)) %>% 
  rename(`Baseline median peck rate / per min` = Estimate)) %>%
  pander()
n pigeons observed Baseline median peck rate / per min Est.Error Q2.5 Q97.5
35 1.32 0.51 0.54 2.53

\(~\)

Experimental data

\(~\)

Exploring allocation versus expectation 2.0

\(~\)

Once again, we expect that attention paid to and/or comprehension of the primer statement has a large effect on observers’ perception of pigeon foraging.

Lets again fit our two models:

  1. a model with allocated primer (Bias_treatment) as the predictor variable

  2. a model with indicated hunger expectation (Expectation) as the predictor variable

\(~\)

Model 1: allocated primer

# First let's model the effect of bias treatment on peck rate

peck_model_treatment <- 
  brm(Peck_rate ~ 0 + Bias_treatment + (1|Observer_ID),
      data = data_peck, family = negbinomial,
      prior = c(prior(normal(0, 1.5), class = b),
                prior(exponential(1), class = sd)),
      iter = 6000, warmup = 2000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.9, max_treedepth = 12),
      seed = 1, file = "fits/peck_model_treatment")

peck_model_treatment <- add_criterion(peck_model_treatment, criterion = "loo", file = "fits/peck_model_treatment")
  
peck_model_treatment
##  Family: negbinomial 
##   Links: mu = log; shape = identity 
## Formula: Peck_rate ~ 0 + Bias_treatment + (1 | Observer_ID) 
##    Data: data_peck (Number of observations: 156) 
##   Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
##          total post-warmup draws = 16000
## 
## Group-Level Effects: 
## ~Observer_ID (Number of levels: 78) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.21      0.15     0.01     0.54 1.00     4493     7497
## 
## Population-Level Effects: 
##                        Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Bias_treatmentHungry       2.32      0.13     2.06     2.57 1.00    14993
## Bias_treatmentSatiated     2.16      0.14     1.89     2.44 1.00    19527
##                        Tail_ESS
## Bias_treatmentHungry      10405
## Bias_treatmentSatiated    11645
## 
## Family Specific Parameters: 
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## shape     0.91      0.13     0.69     1.18 1.00    13608     8978
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
peck_model_treatment_gender <- 
  brm(Peck_rate ~ 0 + Gender * Bias_treatment + (1|Observer_ID),
      data = data_peck, family = negbinomial,
      prior = c(prior(normal(0, 1.5), class = b),
                prior(exponential(1), class = sd)),
      iter = 6000, warmup = 2000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.9, max_treedepth = 12),
      seed = 1, file = "fits/peck_model_treatment_gender")

Table S3. The estimated peck rate of foraging pigeons, split by the primer observers were allocated.

new_data %>% 
  bind_cols(fitted(peck_model_treatment, newdata = new_data, summary = T, re_formula = NA) %>% 
              as_tibble() %>% 
              mutate(across(1:4, round, 2))) %>% 
  left_join(data_peck %>% group_by(Bias_treatment) %>% 
              distinct(Observer_ID) %>% summarise(`n pigeons observed` = n())) %>% 
  rename("Estimated peck rate" = Estimate,
         "Bias treatment" = Bias_treatment) %>% 
  bind_rows(fitted(baseline_peck_model_zi, summary = T, re_formula = NA) %>% 
              as_tibble() %>%
              distinct(Estimate, .keep_all = T) %>% 
              mutate(across(1:4, round, 2)) %>% 
              rename("Estimated peck rate" = Estimate) %>% 
              mutate(`Bias treatment` = "Baseline") %>% 
              bind_cols(baseline_data %>% 
                          distinct(Pigeon_ID) %>% 
                          summarise(`n pigeons observed` = length(Pigeon_ID)))) %>% 
  select(`Bias treatment`, `n pigeons observed`, everything()) %>% 
  pander(split.cell = 20, split.table = Inf)
Bias treatment n pigeons observed Estimated peck rate Est.Error Q2.5 Q97.5
Hungry 42 10.23 1.34 7.83 13.12
Satiated 36 8.74 1.24 6.59 11.44
Baseline 35 1.32 0.51 0.54 2.53

Model 2: Indicated expectation

# fit the same model, except using participant expectation rather than allocated bias treatment

peck_model_expectation <- brm(Peck_rate ~ 0 + Expectation + (1|Observer_ID),
                                     data = data_peck, family = negbinomial,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = sd)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.95, max_treedepth = 12),
                                     seed = 1, file = "fits/peck_model_expectation")

peck_model_expectation <- add_criterion(peck_model_expectation, criterion = "loo", file = "fits/peck_model_expectation")


peck_model_expectation
##  Family: negbinomial 
##   Links: mu = log; shape = identity 
## Formula: Peck_rate ~ 0 + Expectation + (1 | Observer_ID) 
##    Data: data_peck (Number of observations: 156) 
##   Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
##          total post-warmup draws = 16000
## 
## Group-Level Effects: 
## ~Observer_ID (Number of levels: 78) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.18      0.13     0.01     0.48 1.00     4710     7228
## 
## Population-Level Effects: 
##                     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## ExpectationHungry       2.41      0.12     2.18     2.66 1.00    16705    11820
## ExpectationSatiated     2.00      0.14     1.73     2.28 1.00    18644    12176
## 
## Family Specific Parameters: 
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## shape     0.93      0.12     0.71     1.20 1.00    14884    11083
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
#loo_compare(peck_model_treatment, peck_model_expectation)

peck_model_expectation_gender <- brm(Peck_rate ~ 0 + Gender * Expectation + (1|Observer_ID),
                                     data = data_peck, family = negbinomial,
                                     prior = c(prior(normal(0, 1.5), class = b),
                                               prior(exponential(1), class = sd)),
                                     iter = 6000, warmup = 2000, chains = 4, cores = 4,
                                     control = list(adapt_delta = 0.95, max_treedepth = 12),
                                     seed = 1, file = "fits/peck_model_expectation_gender")

Table S4. The estimated peck rate of foraging pigeons, split by the indicated expectation of the observers.

new_data_2 %>% 
  bind_cols(fitted(peck_model_expectation, newdata = new_data_2, summary = T, re_formula = NA) %>% 
              as_tibble() %>% 
              mutate(across(1:4, round, 2))) %>% 
  left_join(data_peck %>% group_by(Expectation) %>% 
              distinct(Observer_ID) %>% summarise(`n pigeons observed` = n())) %>% 
  rename("Estimated peck rate" = Estimate,
         "Indicated expectation" = Expectation) %>% 
  bind_rows(fitted(baseline_peck_model_zi, summary = T, re_formula = NA) %>% 
              as_tibble() %>%
              distinct(Estimate, .keep_all = T) %>% 
              mutate(across(1:4, round, 2)) %>% 
              rename("Estimated peck rate" = Estimate) %>% 
              mutate(`Indicated expectation` = "Baseline") %>% 
              bind_cols(baseline_data %>% 
                          distinct(Pigeon_ID) %>% 
                          summarise(`n pigeons observed` = length(Pigeon_ID)))) %>% 
  select(`Indicated expectation`, `n pigeons observed`, everything()) %>% 
  pander(split.cell = 20, split.table = Inf)
Indicated expectation n pigeons observed Estimated peck rate Est.Error Q2.5 Q97.5
Hungry 44 11.27 1.4 8.81 14.29
Satiated 34 7.46 1.06 5.62 9.81
Baseline 35 1.32 0.51 0.54 2.53

\(~\)

Build Figure 1e-h

\(~\)

Get posterior means and difference contrasts

# treatment model

peck_draws_treatment <-
  as_draws_df(peck_model_treatment) %>% 
  mutate(Hungry = exp(b_Bias_treatmentHungry),
         Satiated = exp(b_Bias_treatmentSatiated),
         diff_contrast = (Hungry - Satiated)) %>% 
  select(Hungry, Satiated, diff_contrast) %>%
  bind_cols(baseline_peck_predictions %>% select(Baseline_estimate)) %>% 
  pivot_longer(names_to = "Treatment", values_to = "Posterior_estimate", cols = 1:3) %>% 
  mutate(Predictor = "Allocated primer")


p6 <- 
    peck_draws_treatment %>% 
    filter(Treatment != "diff_contrast") %>% 
    ggplot(aes(x = Treatment, y = Posterior_estimate)) +
    stat_slab(aes(y = Baseline_estimate),
              linetype = 2, linewidth = 0.8, slab_fill = "white",
              colour = "black") +
    stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
                 point_interval = "median_qi", point_fill = "white",
                 shape = 21, point_size = 4, stroke = 1.5) +
    scale_fill_manual(values = met.brewer("Hiroshige", 2)) +
    coord_flip(ylim = c(0, 20)) +
    #geom_vline(xintercept = 0, linetype = 2) +
    #scale_y_continuous(breaks = c(, 0, 1)) +
    xlab("Allocated primer") +
    ylab("Estimated pecks per min") +
    theme_bw() + 
    theme(legend.position = "none",
          panel.grid.minor = element_blank(),
          text = element_text(size = 14))

p7 <-
  peck_draws_treatment %>% 
  filter(Treatment == "diff_contrast") %>% 
  ggplot(aes(y = Posterior_estimate)) + 
   stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5, scale =0.5) +
  scale_fill_manual(values = met.brewer("Hiroshige")[4]) +
  coord_flip(ylim = c(-5, 12)) +
  geom_hline(yintercept = 0, linetype = 2, linewidth = 0.75) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab(NULL) +
  ylab("Hungry - Satiated difference\ncontrast (pecks per min)") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        text = element_text(size = 14))

# expectation model

peck_draws_expectation <-
  as_draws_df(peck_model_expectation) %>% 
  mutate(Hungry = exp(b_ExpectationHungry),
         Satiated = exp(b_ExpectationSatiated),
         diff_contrast = (Hungry - Satiated)) %>% 
  select(Hungry, Satiated, diff_contrast) %>% 
  bind_cols(baseline_peck_predictions %>% select(Baseline_estimate)) %>% 
  pivot_longer(names_to = "Treatment", values_to = "Posterior_estimate", cols = 1:3) %>% 
  mutate(Predictor = "Allocated primer")

p8 <-
  peck_draws_expectation %>% 
  filter(Treatment != "diff_contrast") %>% 
  ggplot(aes(x = Treatment, y = Posterior_estimate)) + 
  stat_slab(aes(y = Baseline_estimate),
              linetype = 2, linewidth = 0.8, slab_fill = "white",
              colour = "black") +
    stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5) +
  scale_fill_manual(values = met.brewer("Hiroshige", 2)) +
  coord_flip(ylim = c(0, 20)) +
  #geom_vline(xintercept = 0, linetype = 2) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab("Indicated expectation") +
  ylab("Estimated pecks per min") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        text = element_text(size = 14))

p9 <-
  peck_draws_expectation %>% 
  filter(Treatment == "diff_contrast") %>% 
  ggplot(aes(y = Posterior_estimate)) + 
   stat_halfeye(aes(fill = Treatment), .width = c(0.66, 0.95), alpha = 0.9,
               point_interval = "median_qi", point_fill = "white",
               shape = 21, point_size = 4, stroke = 1.5, scale =0.5) +
  scale_fill_manual(values = met.brewer("Hiroshige")[4]) +
  coord_flip(ylim = c(-5, 12)) +
  geom_hline(yintercept = 0, linetype = 2, linewidth = 0.75) +
  #scale_y_continuous(breaks = c(, 0, 1)) +
  xlab(NULL) +
  ylab("Hungry - Satiated difference\ncontrast (pecks per min)") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        text = element_text(size = 14))

\(~\)

Find the difference between baseline and observer estimates

Table S5. The degree to which each group of observer’s overestimates feeding rate (number of ground pecks per minute)

baseline_peck_predictions %>% select(Baseline_estimate) %>%  bind_cols(
  
  as_draws_df(peck_model_treatment) %>% 
    mutate(Hungry = exp(b_Bias_treatmentHungry),
           Satiated = exp(b_Bias_treatmentSatiated)) %>% 
    select(Hungry, Satiated)) %>% 
  mutate(`Bias treatment Satiated / Baseline` = Satiated / Baseline_estimate,
         `Bias treatment Hungry / Baseline` = Hungry / Baseline_estimate) %>% 
  select(contains("Bias")) %>% 
  pivot_longer(cols = everything(), values_to = "estimate", names_to = "Stat") %>% 
  group_by(Stat) %>% 
  summarise_draws("median", "sd", ~quantile(.x, probs = c(0.025, 0.975), na.rm = TRUE), .cores = 4) %>% 
  select(-variable) %>% 
  
  bind_rows(
    
    baseline_peck_predictions %>% select(Baseline_estimate) %>%  bind_cols(
      
      as_draws_df(peck_model_expectation) %>% 
        mutate(Hungry = exp(b_ExpectationHungry),
               Satiated = exp(b_ExpectationSatiated)) %>% 
        select(Hungry, Satiated)) %>% 
      mutate(`Expectation Satiated / Baseline` = Satiated / Baseline_estimate,
             `Expectation Hungry / Baseline` = Hungry / Baseline_estimate) %>% 
      select(contains("Expectation")) %>% 
      pivot_longer(cols = everything(), values_to = "estimate", names_to = "Stat") %>% 
      group_by(Stat) %>% 
      summarise_draws("median", "sd", ~quantile(.x, probs = c(0.025, 0.975), na.rm = TRUE), .cores = 4) %>% 
      select(-variable)
  ) %>% 
  pander()
Stat median sd 2.5% 97.5%
Bias treatment Hungry / Baseline 7.883 4.111 3.728 19.04
Bias treatment Satiated / Baseline 6.713 3.562 3.149 16.48
Expectation Hungry / Baseline 8.67 4.554 4.108 20.94
Expectation Satiated / Baseline 5.722 3.065 2.688 14

Figure 1

Option 1

(p2 + p3) / (p4 + p5) / (p6 + p7) / (p8 + p9) +
   plot_annotation(tag_levels = 'a')

Figure 1. Posterior mean estimates and difference contrasts for observer estimated group foraging percentage and individual feeding rates. The coloured area is the posterior distribution and the white point is the mean estimate with associated 67% and 95% credible intervals. The distributions shown with dashed lines are the posterior for baseline peck rate, estimated from a random sample of pigeons appearing in the video.

Session info

sessionInfo() %>% pander

R version 4.3.1 (2023-06-16 ucrt)

Platform: x86_64-w64-mingw32/x64 (64-bit)

locale: LC_COLLATE=English_Australia.utf8, LC_CTYPE=English_Australia.utf8, LC_MONETARY=English_Australia.utf8, LC_NUMERIC=C and LC_TIME=English_Australia.utf8

attached base packages: grid, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: ggdag(v.0.2.10), png(v.0.1-8), pander(v.0.6.5), DT(v.0.28), patchwork(v.1.1.2), kableExtra(v.1.3.4), MetBrewer(v.0.2.0), tidybayes(v.3.0.4), loo(v.2.6.0), brms(v.2.19.0), Rcpp(v.1.0.11), lubridate(v.1.9.2), forcats(v.1.0.0), stringr(v.1.5.0), dplyr(v.1.1.2), purrr(v.1.0.1), readr(v.2.1.4), tidyr(v.1.3.0), tibble(v.3.2.1), ggplot2(v.3.4.2) and tidyverse(v.2.0.0)

loaded via a namespace (and not attached): tensorA(v.0.36.2), rstudioapi(v.0.15.0), jsonlite(v.1.8.7), magrittr(v.2.0.3), farver(v.2.1.1), rmarkdown(v.2.23), vctrs(v.0.6.3), base64enc(v.0.1-3), webshot(v.0.5.5), htmltools(v.0.5.5), dagitty(v.0.3-1), distributional(v.0.3.2), curl(v.5.0.1), sass(v.0.4.7), StanHeaders(v.2.26.27), bslib(v.0.5.0), htmlwidgets(v.1.6.2), plyr(v.1.8.8), zoo(v.1.8-12), cachem(v.1.0.8), igraph(v.1.5.0.1), mime(v.0.12), lifecycle(v.1.0.3), pkgconfig(v.2.0.3), colourpicker(v.1.2.0), Matrix(v.1.5-4.1), R6(v.2.5.1), fastmap(v.1.1.1), shiny(v.1.7.4.1), digest(v.0.6.33), colorspace(v.2.1-0), ps(v.1.7.5), crosstalk(v.1.2.0), labeling(v.0.4.2), fansi(v.1.0.4), timechange(v.0.2.0), polyclip(v.1.10-4), httr(v.1.4.6), abind(v.1.4-5), compiler(v.4.3.1), bit64(v.4.0.5), withr(v.2.5.0), backports(v.1.4.1), inline(v.0.3.19), shinystan(v.2.6.0), viridis(v.0.6.4), highr(v.0.10), pkgbuild(v.1.4.2), ggforce(v.0.4.1), MASS(v.7.3-60), gtools(v.3.9.4), tools(v.4.3.1), httpuv(v.1.6.11), threejs(v.0.3.3), glue(v.1.6.2), callr(v.3.7.3), nlme(v.3.1-162), promises(v.1.2.0.1), checkmate(v.2.2.0), reshape2(v.1.4.4), generics(v.0.1.3), gtable(v.0.3.3), tzdb(v.0.4.0), hms(v.1.1.3), tidygraph(v.1.2.3), xml2(v.1.3.5), utf8(v.1.2.3), ggrepel(v.0.9.3), pillar(v.1.9.0), ggdist(v.3.3.0), markdown(v.1.7), vroom(v.1.6.3), posterior(v.1.4.1), later(v.1.3.1), tweenr(v.2.0.2), lattice(v.0.21-8), bit(v.4.0.5), tidyselect(v.1.2.0), miniUI(v.0.1.1.1), knitr(v.1.43), arrayhelpers(v.1.1-0), gridExtra(v.2.3), V8(v.4.3.3), svglite(v.2.1.1), stats4(v.4.3.1), xfun(v.0.39), graphlayouts(v.1.0.0), bridgesampling(v.1.1-2), matrixStats(v.1.0.0), rstan(v.2.26.22), stringi(v.1.7.12), boot(v.1.3-28.1), yaml(v.2.3.7), evaluate(v.0.21), codetools(v.0.2-19), ggraph(v.2.1.0), cli(v.3.6.1), RcppParallel(v.5.1.7), shinythemes(v.1.2.0), xtable(v.1.8-4), systemfonts(v.1.0.4), munsell(v.0.5.0), processx(v.3.8.2), jquerylib(v.0.1.4), coda(v.0.19-4), svUnit(v.1.0.6), parallel(v.4.3.1), rstantools(v.2.3.1.1), ellipsis(v.0.3.2), prettyunits(v.1.1.1), dygraphs(v.1.1.1.6), bayesplot(v.1.10.0), Brobdingnag(v.1.2-9), viridisLite(v.0.4.2), mvtnorm(v.1.2-2), scales(v.1.2.1), xts(v.0.13.1), crayon(v.1.5.2), rlang(v.1.1.1), rvest(v.1.0.3) and shinyjs(v.2.1.0)

LS0tDQp0aXRsZTogJ0FuIHVuZGVyZ3JhZHVhdGUgY2xhc3Nyb29tIGV4cGVyaW1lbnQgZGVtb25zdHJhdGVzIHRoZSBwb3RlbnRpYWwgb2Ygc3ViY29uc2Npb3VzIGJpYXMgdG8gaW5mbHVlbmNlIGRhdGEgY29sbGVjdGlvbiBpbiBhbmltYWwgYmVoYXZpb3VyJw0KYXV0aG9yOiAnVGhvbWFzIEtlYW5leSwgVGhlcmVzYSBKb25lcyBhbmQgUmFvdWwgTXVsZGVyJyANCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBkZXB0aDogMQ0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogeWV0aQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNhY2hlID0gRkFMU0UpDQpgYGANCg0KIyBUZWFjaGluZyBtYXRlcmlhbHMNCg0KJH4kDQoNCioq4oCYaHVuZ3J5IGZvcmFnZXLigJkgcHJpbWVyKio6IA0KDQoqKuKAmHNhdGlhdGVkIGZvcmFnZXLigJkgcHJpbWVyKio6DQoNClBpZ2VvbiBmb290YWdlIGlzIGF2YWlsYWJsZSBvbiB0aGUgZ2l0aHViIHBhZ2UgYXNzb2NpYXRlZCB3aXRoIHRoaXMgcmVwb3J0LiBJdCBjYW4gYmUgYWNjZXNzZWQgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL3RvbWtlYW5leS9CaWFzZWRfcGlnZW9ucyBieSBkb3dubG9hZGluZyB0aGUgYHBpZ2Vvbl92aWRlby5tcDRgIGZpbGUuDQoNCiR+JA0KDQojIExvYWQgcGFja2FnZXMgYW5kIHRoZSBkYXRhDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgdGlkeSBzdHlsZSBjb2RpbmcNCmxpYnJhcnkoYnJtcykgIyBCYXllc2lhbiBtb2RlbHMNCmxpYnJhcnkobG9vKSAjIGZvciBpbmZvcm1hdGlvbiBjcml0ZXJpYQ0KbGlicmFyeSh0aWR5YmF5ZXMpICMgQmF5ZXNpYW4gYWVzdGhldGljcw0KbGlicmFyeShNZXRCcmV3ZXIpICMgY29sb3Vycw0KbGlicmFyeShrYWJsZUV4dHJhKSAjIHRhYmxlcw0KbGlicmFyeShwYXRjaHdvcmspICMgcHV0dGluZyBwbG90cyB0b2dldGhlcg0KbGlicmFyeShEVCkgIyBmb3Igc2VhcmNoLSBhbmQgc2F2ZWFibGUgdGFibGVzDQpsaWJyYXJ5KHBhbmRlcikgIyBmb3Igc2ltcGxlciB0YWJsZXMNCmxpYnJhcnkocG5nKSAjIHRvIGxvYWQgaW1hZ2VzDQpsaWJyYXJ5KGdyaWQpICMgdG8gcGxvdCBpbWFnZXMNCmxpYnJhcnkoZ2dkYWcpICMgdG8gZHJhdyBkYWdzDQpgYGANCg0KYGBge3J9DQoNCmRhdGEgPC0gcmVhZF9jc3YoImRhdGEvcGlnZW9uX2RhdGEuY3N2IikgJT4lIA0KICBtdXRhdGUoU3R1ZGVudF9JRCA9IGFzLmZhY3RvcihTdHVkZW50X0lEKSwNCiAgICAgICAgIFllYXIgPSBhcy5mYWN0b3IoWWVhciksDQogICAgICAgICBGb3JhZ2luZ19wcm9wID0gKEZvcmFnaW5nX3BlcmNlbnRhZ2UgLyAxMDApKSAlPiUNCiAgZmlsdGVyKFllYXIgJWluJSBjKCIyMDIxIiwgIjIwMjIiLCAiMjAyMyIpLA0KICAgICAgICAgRm9yYWdpbmdfcGVyY2VudGFnZSAhPSAiTkEiLA0KICAgICAgICAgUHJpbWVyX3VuZGVyc3Rvb2QgIT0gIk5BIikgJT4lDQogIGZpbHRlcihTdHVkZW50X0lEICE9ICI2MCIgJiBTdHVkZW50X0lEICE9ICI2OCIgJiBTdHVkZW50X0lEICE9ICI3MCIgJiBTdHVkZW50X0lEICE9ICI3MiIpICU+JSAjIHJlbW92ZSBzdHVkZW50cyB0aGF0IGNvbXBsZXRlZCB0aGUgdGFzayBtdWx0aXBsZSB0aW1lcw0KICAjU3R1ZGVudF9JRCAlaW4lIGMoIjYwIiwgIjY4IiwgIjcwIiwgIjcyIikpICU+JSANCiAgc2VsZWN0KC1jKEZpcnN0X25hbWUsIFN1cm5hbWUsIFBlY2tfbWVhbikpICU+JSAgIyByZW1vdmUgbmFtZXMgd2hlbiByZWFkeQ0KICBsZWZ0X2pvaW4oDQogICAgcmVhZF9jc3YoImRhdGEvZ2VuZGVyX2RhdGEuY3N2IikgJT4lIA0KICAgICAgbXV0YXRlKFN0dWRlbnRfSUQgPSBhcy5mYWN0b3IoU3R1ZGVudF9JRCkpDQogICkgJT4lIA0KICByZW5hbWUoT2JzZXJ2ZXJfSUQgPSBTdHVkZW50X0lEKSAlPiUgDQogIHNlbGVjdChPYnNlcnZlcl9JRCwgWWVhciwgR2VuZGVyLCBldmVyeXRoaW5nKCkpDQoNCmRhdGFfcGVjayA8LSANCiAgZGF0YSAlPiUNCiAgZmlsdGVyKFBlY2tfcmF0ZV8yICE9ICJOQSIpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBQZWNrX3JhdGVfMTpQZWNrX3JhdGVfMiwgbmFtZXNfdG8gPSAiVHJpYWwiLA0KICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlBlY2tfcmF0ZSIpDQogIA0KIyBDcmVhdGUgYSBmdW5jdGlvbiB0byBidWlsZCBIVE1MIHNlYXJjaGFibGUgdGFibGVzDQoNCm15X2RhdGFfdGFibGUgPC0gZnVuY3Rpb24oZGYpew0KICBkYXRhdGFibGUoDQogICAgZGYsIHJvd25hbWVzPUZBTFNFLA0KICAgIGF1dG9IaWRlTmF2aWdhdGlvbiA9IFRSVUUsDQogICAgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgICJCdXR0b25zIiksDQogICAgb3B0aW9ucyA9IGxpc3QoDQogICAgICBkb20gPSAnQmZydGlwJywNCiAgICAgIGRlZmVyUmVuZGVyPVRSVUUsDQogICAgICBzY3JvbGxYPVRSVUUsIHNjcm9sbFk9NDAwLA0KICAgICAgc2Nyb2xsQ29sbGFwc2U9VFJVRSwNCiAgICAgIGJ1dHRvbnMgPQ0KICAgICAgICBsaXN0KCdwYWdlTGVuZ3RoJywgJ2NvbHZpcycsICdjc3YnLCBsaXN0KA0KICAgICAgICAgIGV4dGVuZCA9ICdwZGYnLA0KICAgICAgICAgIHBhZ2VTaXplID0gJ0E0JywNCiAgICAgICAgICBvcmllbnRhdGlvbiA9ICdsYW5kc2NhcGUnLA0KICAgICAgICAgIGZpbGVuYW1lID0gJ2Z1bGxfZGF0YXNldCcpKSwNCiAgICAgIHBhZ2VMZW5ndGggPSA3OA0KICAgICkNCiAgKQ0KfQ0KDQpteV9kYXRhX3RhYmxlKGRhdGEpDQpgYGANCg0KKipDb2x1bW4gZXhwbGFuYXRpb25zKioNCg0KKipPYnNlcnZlcl9JRCoqOiB1bmlxdWUsIGFub255bWlzZWQgaWRlbnRpZmllciBmb3IgZWFjaCBvYnNlcnZlci4NCg0KKipZZWFyKio6IHllYXIgdGhhdCB0aGUgZXhwZXJpbWVudCB3YXMgY29uZHVjdGVkLg0KDQoqKkdlbmRlcioqOiB1cG9uIGVucm9sbG1lbnQgYXQgVGhlIFVuaXZlcnNpdHkgb2YgTWVsYm91cm5lLCBzdHVkZW50cyBhcmUgYXNrZWQgdG8gaW5kaWNhdGUgdGhlaXIgdGl0bGUuIFdlIGlkZW50aWZpZWQgd29tZW4gYXMgb2JzZXJ2ZXJzIHRoYXQgYW5zd2VyZWQgIk1pc3MiIG9yICJNcyIgYW5kIE1lbiBhcyB0aG9zZSB3aG8gdGhhdCBhbnN3ZXJlZCAiTXIiLiBUaG9zZSB3aXRoIGVudGlyZWx5IG1pc3NpbmcgZW50cmllcyB3ZXJlIGNvZGVkIGFzICJOQSIuICANCg0KKipCaWFzX3RyZWF0bWVudCoqOiB0aGUgcHJpbWVyIHRoZSBvYnNlcnZlciByZWNlaXZlZCwgd2hlcmUgJ3NhdGlhdGVkJyBpbmRpY2F0ZXMgdGhhdCB0aGUgb2JzZXJ2ZXJzIHdlcmUgcHJvdmlkZWQgaW5mb3JtYXRpb24gcHJpb3IgdG8gYSB0cmlhbCB0aGF0IHN1Z2dlc3RlZCBwaWdlb25zIHdlcmUgZmVsbCBmZWQsIHdoZXJlYXMgJ2h1bmdyeScgaW5kaWNhdGVkIHRoYXQgdGhlIHBpZ2VvbnMgd2VyZSBpbiBwb29yIGNvbmRpdGlvbiBhbmQgaHVuZ3J5Lg0KDQoqKkV4cGVjdGF0aW9uKio6IHdlIGFza2VkIHRoZSBvYnNlcnZlcnMgdG8gaW5kaWNhdGUgd2hldGhlciB0aGV5IHRob3VnaHQgdGhlIHBpZ2VvbnMgd291bGQgYmUgaHVuZ3J5IG9yIHNhdGlhdGVkLiBXZSBpbmNsdWRlZCB0aGlzIHF1ZXN0aW9uIHRvIHRlc3Qgd2hldGhlciBvYnNlcnZlcnMgd2VyZSBhcHByb3ByaWF0ZWx5IHByaW1lZCBieSB0aGVpciBiaWFzIHRyZWF0bWVudC4NCg0KKipQcmltZXJfdW5kZXJzdG9vZCoqOiBkaWQgdGhlIG9ic2VydmVyJ3MgZXhwZWN0YXRpb24gbWF0Y2ggdGhlIHByaW1lciB0aGV5IHJlY2VpdmVkPw0KDQoqKkZvcmFnaW5nX3BlcmNlbnRhZ2UqKjogdGhlIHBlcmNlbnRhZ2Ugb2YgcGlnZW9ucyB0aGF0IG9ic2VydmVycyBlc3RpbWF0ZWQgdG8gYmUgZm9yYWdpbmcgb3ZlciBhIDE1IHNlY29uZCBwZXJpb2QsIHdoaWxlIG9ic2VydmluZyBhIGxhcmdlIGZsb2NrLg0KDQoqKlBlY2tfcmF0ZV8xKio6IHRoZSBudW1iZXIgb2YgdGltZXMgYSBzaW5nbGUgY2hvc2VuIHBpZ2VvbiBwZWNrZWQgdGhlIGdyb3VuZCBvdmVyIGEgMTUgc2Vjb25kIHBlcmlvZC4NCg0KKipQZWNrX3JhdGVfMioqOiB0aGUgbnVtYmVyIG9mIHRpbWVzIGEgc2Vjb25kIGNob3NlbiBwaWdlb24gcGVja2VkIHRoZSBncm91bmQgb3ZlciBhIDE1IHNlY29uZCBwZXJpb2QuDQoNCioqRm9yYWdpbmdfcHJvcCoqOiBwcm9wb3J0aW9uIG9mIHBpZ2VvbnMgZXN0aW1hdGVkIHRvIGJlIGZvcmFnaW5nIA0KDQokfiQNCg0KIyBRdWVzdGlvbiAxOiBpcyBlc3RpbWF0aW9uIG9mIGZvcmFnaW5nIHBlcmNlbnRhZ2UgYWZmZWN0ZWQgYnkgYmlhcyBtYW5pcHVsYXRpb25zPw0KDQokfiQNCg0KIyMgRXhwbG9yaW5nIGFsbG9jYXRpb24gdmVyc3VzIGV4cGVjdGF0aW9uIDEgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KJH4kDQoNCldlIGZpbmQgdGhhdCAqKjIyIG9mIHRoZSA3OCBvYnNlcnZlcnMqKiBpbmRpY2F0ZWQgYSBmZWVkaW5nIG1vdGl2YXRpb24gZXhwZWN0YXRpb24gb3Bwb3NpdGUgdG8gdGhhdCBpbXBsaWVkIGJ5IHRoZSBwcmltZXIgdGhleSB3ZXJlIGFsbG9jYXRlZC4gDQoNClRoaXMgc3VnZ2VzdHMgdGhhdCBgRXhwZWN0YXRpb25gIG1heSBiZSBhIGJldHRlciBwcmVkaWN0b3Igb2YgZm9yYWdpbmcgZXN0aW1hdGlvbiB0aGFuIGFsbG9jYXRlZCBgQmlhc190cmVhdG1lbnRgLiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgYW5kIGFsbCBvdGhlciB2YXJpYWJsZXMgdGhhdCB3ZSBleHBlY3QgdG8gcGxheSBhIHJvbGUgaW4gdGhpcyBzeXN0ZW0gYXJlIGRlcGljdGVkIGluIEZpZ3VyZSAxLg0KDQpXZSBleHBsaWNpdGx5IGFzc2VzcyB0aGUgZWZmZWN0IG9mIHRyZWF0bWVudCBhbmQgZXhwZWN0YXRpb24gYnkgZml0dGluZyB0d28gbW9kZWxzOg0KDQoxLiBhIG1vZGVsIHdpdGggYWxsb2NhdGVkIHByaW1lciAoYEJpYXNfdHJlYXRtZW50YCkgYXMgdGhlIHByZWRpY3RvciB2YXJpYWJsZSANCg0KMi4gYSBtb2RlbCB3aXRoIGluZGljYXRlZCBodW5nZXIgZXhwZWN0YXRpb24gKGBFeHBlY3RhdGlvbmApIGFzIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUNCg0KJH4kDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0KZ2dfc2ltcGxlX2RhZyA8LSBmdW5jdGlvbihkKSB7DQogIGQgJT4lIA0KICAgIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5LCB4ZW5kID0geGVuZCwgeWVuZCA9IHllbmQsIGNvbG91ciA9IFZhcmlhYmxlcykpICsNCiAgICBnZW9tX2RhZ19wb2ludCgpICsNCiAgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIkluY2x1ZGVkIGluIG1vZGVsIiA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIpWzRdLCAiTm90IGluY2x1ZGVkIGluIG1vZGVsIiA9ICJncmV5ODAiKSkgKw0KICAgIGdlb21fZGFnX3RleHQoY29sb3IgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiKVs3XSkgKw0KICAgIGdlb21fZGFnX2VkZ2VzKCkgKyANCiAgICB0aGVtZV9kYWcoKSsNCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQp9DQoNCg0Kb2JzZXJ2ZXJfYmlhc19kYWcgPC0gZGFnaWZ5KEVGIH4gUEVXICsgUEVNICsgU0IgKyBURiwNCiAgICAgICAgUEVXIH4gQlQsDQogICAgICAgIFBFTSB+IEJULA0KICAgICAgICBTQiB+IFBFVyArIFBFTSwNCiAgICAgICBsYWJlbHMgPSBjKCJURiIgPSAiVHJ1ZVxuIEZvcmFnaW5nIiwgDQogICAgICAgICAgICAgICAgICAiRUYiID0gIkVzdGltYXRlZFxuIEZvcmFnaW5nIiwNCiAgICAgICAgICAgICAgICAgICJQRVciID0gIlByaW9yXG4gRXhwZWN0YXRpb24gTWVuIiwNCiAgICAgICAgICAgICAgICAgICJQRU0iID0gIlByaW9yXG4gRXhwZWN0YXRpb24gV29tZW4iLA0KICAgICAgICAgICAgICAgICAgIkJUIiA9ICJCaWFzXG4gVHJlYXRtZW50IiwNCiAgICAgICAgICAgICAgICAgICJTQiIgPSAiU2VsZWN0aW9uXG4gQmlhcyIpKSAlPiUgDQogIHRpZHlfZGFnaXR0eShzZWVkID0gNSkNCiAgDQogIA0KIG9ic2VydmVyX2JpYXNfZGFnIDwtIGxlZnRfam9pbihvYnNlcnZlcl9iaWFzX2RhZyRkYXRhLCB0aWJibGUobmFtZSA9IGMoIkJUIiwgIkVGIiwgIlBFVyIsICJQRU0iLCAiU0IiLCAiVEYiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmFyaWFibGVzID0gYygiSW5jbHVkZWQgaW4gbW9kZWwiLCAiSW5jbHVkZWQgaW4gbW9kZWwiLCAiSW5jbHVkZWQgaW4gbW9kZWwiLCAiSW5jbHVkZWQgaW4gbW9kZWwiLCAiTm90IGluY2x1ZGVkIGluIG1vZGVsIiwgIk5vdCBpbmNsdWRlZCBpbiBtb2RlbCIpKSkgJT4lIA0KICAgDQogZ2dfc2ltcGxlX2RhZygpDQoNCg0Kb2JzZXJ2ZXJfYmlhc19kYWcNCg0KIyoqRmlndXJlIDEqKi4gQSBkaXJlY3QgYWNyeWxpYyBkaWFncmFtIHNob3dpbmcgdGhlIGZsb3cgb2YgY2F1c2F0aW9uIGluIG91ciBiaW9sb2dpY2FsIHN5c3RlbS4gT3VyIGJpYXMgdHJlYXRtZW50IChCVCkgd2FzIGRlc2lnbmVkIHRvIGFmZmVjdCB0aGUgcHJpb3IgZXhwZWN0YXRpb24gKFBFKSBvZiBvYnNlcnZlcidzLCBhIHN1YnNldCBvZiB3aGljaCB3ZXJlIHdvbWVuIChQRVcpLCB3aGlsZSB0aGUgcmVtYWluaW5nIHdlcmUgbWVuIChQRU0pLiBQcmlvciBleHBlY3RhdGlvbnMgbWF5IGFmZmVjdCB0aGUgZXN0aW1hdGVkIGxldmVsIG9mIGZvcmFnaW5nIChFRikgZGlyZWN0bHksIG9yIG1vcmUgc3BlY2lmaWNhbGx5IHRocm91Z2ggYmlhc2VkIHNlbGVjdGlvbiBvZiBwYXJ0aWN1bGFyIGZvcmFnZXJzIChTQikuIEVzdGltYXRlZCBmb3JhZ2luZyBpcyBhbHNvIGFmZmVjdGVkIGJ5IHRoZSB0cnVlIGxldmVsIG9mIGZvcmFnaW5nIChURikgY2FycmllZCBvdXQgYnkgdGhlIGZsb2NrIG9mIHBpZ2VvbnMgaW4gdGhlIGZvb3RhZ2UuIFdlIGh5cG90aGVzaXNlZCB0aGF0IF9hIHByaW9yaV8gZXhwZWN0YXRpb25zIG9mIG9ic2VydmVyJ3Mgd291bGQgYWZmZWN0IHRoZWlyIGZvcmFnaW5nIGVzdGltYXRlcy4gVGhlIHBhdGhzIGNvbm5lY3RpbmcgY29sb3VyZWQgdmFyaWFibGVzIHNob3cgdGhhdCB0aGlzIGNhbiBiZSB0ZXN0ZWQgYnkgbW9kZWxsaW5nIHRoZSBlZmZlY3Qgb2YgYmlhcyB0cmVhdG1lbnQgb24gZXN0aW1hdGVkIGZvcmFnaW5nLCBvciBhbHRlcm5hdGl2ZWx5IGJ5IGRpcmVjdGx5IG1vZGVsbGluZyB0aGUgZWZmZWN0IG9mIHByaW9yIGV4cGVjdGF0aW9uIG9uIGVzdGltYXRlZCBmb3JhZ2luZy4gDQoNCg0KYGBgDQoNCg0KJH4kDQoNCiMjIyBNb2RlbCAxOiBhbGxvY2F0ZWQgcHJpbWVyDQoNCmBgYHtyfQ0KDQojIEZpcnN0IGxldCdzIG1vZGVsIHRoZSBlZmZlY3Qgb2YgYmlhcyB0cmVhdG1lbnQgb24gZm9yYWdpbmcgZXN0aW1hdGlvbiANCg0KZm9yYWdpbmdfbW9kZWxfdHJlYXRtZW50IDwtIGJybShGb3JhZ2luZ19wcm9wIH4gMCArIEJpYXNfdHJlYXRtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCBmYW1pbHkgPSBCZXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gcGhpKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDYwMDAsIHdhcm11cCA9IDIwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOCwgbWF4X3RyZWVkZXB0aCA9IDEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMSwgZmlsZSA9ICJmaXRzL2ZvcmFnaW5nX21vZGVsX3RyZWF0bWVudCIpDQoNCmZvcmFnaW5nX21vZGVsX3RyZWF0bWVudCA8LSBhZGRfY3JpdGVyaW9uKGZvcmFnaW5nX21vZGVsX3RyZWF0bWVudCwgY3JpdGVyaW9uID0gImxvbyIsIGZpbGUgPSAiZml0cy9mb3JhZ2luZ19tb2RlbF90cmVhdG1lbnQiKQ0KDQpmb3JhZ2luZ19tb2RlbF90cmVhdG1lbnQNCg0KZm9yYWdpbmdfbW9kZWxfdHJlYXRtZW50X2dlbmRlciA8LSBicm0oRm9yYWdpbmdfcHJvcCB+IDAgKyBHZW5kZXIgKiBCaWFzX3RyZWF0bWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgZmFtaWx5ID0gQmV0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHBoaSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA2MDAwLCB3YXJtdXAgPSAyMDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjgsIG1heF90cmVlZGVwdGggPSAxMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEsIGZpbGUgPSAiZml0cy9mb3JhZ2luZ19tb2RlbF90cmVhdG1lbnRfZ2VuZGVyIikNCg0KYGBgDQoNCioqVGFibGUgUzEqKi4gUG9zdGVyaW9yIGVzdGltYXRlcyBvZiB0aGUgcGVyY2VudGFnZSBvZiBwaWdlb24gZmVlZGluZyByYXRlLCBzcGxpdCBieSB0aGUgcHJpbWVyIG9ic2VydmVycyB3ZXJlIGFsbG9jYXRlZC4NCg0KYGBge3J9DQpuZXdfZGF0YSA8LSB0aWJibGUoQmlhc190cmVhdG1lbnQgPSBjKCJIdW5ncnkiLCAiU2F0aWF0ZWQiKSkNCg0KbmV3X2RhdGEgJT4lIA0KICBsZWZ0X2pvaW4oZGF0YSAlPiUgZ3JvdXBfYnkoQmlhc190cmVhdG1lbnQpICU+JSBzdW1tYXJpc2UoYG4gb2JzZXJ2ZXJzYCA9IG4oKSkpICU+JSANCiAgY2JpbmQoZml0dGVkKGZvcmFnaW5nX21vZGVsX3RyZWF0bWVudCwgbmV3ZGF0YSA9IG5ld19kYXRhLCBzdW1tYXJ5ID0gVCkgJT4lIA0KICAgICAgICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgfiAueCAqMTAwKSwNCiAgICAgICAgICAgICAgICAgYWNyb3NzKDE6NCwgcm91bmQsIDIpKSkgJT4lIA0KICByZW5hbWUoIkVzdGltYXRlZCBwcm9wb3J0aW9uIGZvcmFnaW5nIiA9IEVzdGltYXRlLA0KICAgICAgICAgIkJpYXMgdHJlYXRtZW50IiA9IEJpYXNfdHJlYXRtZW50KSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KDQpgYGANCg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCiMgYWRkIGdlbmRlciBwcmVkaWN0aW9ucw0KDQpuZXdfZGF0YV9nZW5kZXIgPC0gZXhwYW5kX2dyaWQoQmlhc190cmVhdG1lbnQgPSBjKCJIdW5ncnkiLCAiU2F0aWF0ZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5kZXIgPSBjKCJXb21hbiIsICJNYW4iKSkNCg0KbmV3X2RhdGFfZ2VuZGVyICU+JSANCiAgbGVmdF9qb2luKGRhdGEgJT4lIGdyb3VwX2J5KEdlbmRlciwgQmlhc190cmVhdG1lbnQpICU+JSBzdW1tYXJpc2UoYG4gb2JzZXJ2ZXJzYCA9IG4oKSkgJT4lIA0KICAgICAgICAgIHVuZ3JvdXAoKSAlPiUgZmlsdGVyKCFpcy5uYShHZW5kZXIpKSkgJT4lIA0KICBjYmluZChmaXR0ZWQoZm9yYWdpbmdfbW9kZWxfdHJlYXRtZW50X2dlbmRlciwgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlciwgc3VtbWFyeSA9IFQpICU+JSANCiAgICAgICAgICBhc190aWJibGUoKSAlPiUgDQogICAgICAgICAgbXV0YXRlKGFjcm9zcygxOjQsIH4gLnggKjEwMCksDQogICAgICAgICAgICAgICAgIGFjcm9zcygxOjQsIHJvdW5kLCAyKSkpICU+JSANCiAgcmVuYW1lKCJFc3RpbWF0ZWQgcHJvcG9ydGlvbiBmb3JhZ2luZyIgPSBFc3RpbWF0ZSwNCiAgICAgICAgICJCaWFzIHRyZWF0bWVudCIgPSBCaWFzX3RyZWF0bWVudCkgJT4lIA0KICBwYW5kZXIoc3BsaXQuY2VsbCA9IDIwLCBzcGxpdC50YWJsZSA9IEluZikNCmBgYA0KDQoNCiMjIyBNb2RlbCAyOiBpbmRpY2F0ZWQgZXhwZWN0YXRpb24NCg0KYGBge3J9DQoNCiMgZml0IHRoZSBzYW1lIG1vZGVsLCBleGNlcHQgdXNpbmcgcGFydGljaXBhbnQgZXhwZWN0YXRpb24gcmF0aGVyIHRoYW4gYWxsb2NhdGVkIGJpYXMgdHJlYXRtZW50DQoNCmZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uIDwtIGJybShGb3JhZ2luZ19wcm9wIH4gMCArIEV4cGVjdGF0aW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCBmYW1pbHkgPSBCZXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gcGhpKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDYwMDAsIHdhcm11cCA9IDIwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOCwgbWF4X3RyZWVkZXB0aCA9IDEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMSwgZmlsZSA9ICJmaXRzL2ZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uIikNCg0KZm9yYWdpbmdfbW9kZWxfZXhwZWN0YXRpb24gPC0gYWRkX2NyaXRlcmlvbihmb3JhZ2luZ19tb2RlbF9leHBlY3RhdGlvbiwgY3JpdGVyaW9uID0gImxvbyIsIGZpbGUgPSAiZml0cy9mb3JhZ2luZ19tb2RlbF9leHBlY3RhdGlvbiIpDQoNCmZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uDQoNCmZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uX2dlbmRlciA8LSBicm0oRm9yYWdpbmdfcHJvcCB+IDAgKyBHZW5kZXIgKiBFeHBlY3RhdGlvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgZmFtaWx5ID0gQmV0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHBoaSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA2MDAwLCB3YXJtdXAgPSAyMDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjgsIG1heF90cmVlZGVwdGggPSAxMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEsIGZpbGUgPSAiZml0cy9mb3JhZ2luZ19tb2RlbF9leHBlY3RhdGlvbl9nZW5kZXIiKQ0KDQpgYGANCg0KKipUYWJsZSBTMioqLiBQb3N0ZXJpb3IgZXN0aW1hdGVzIG9mIHRoZSBwZXJjZW50YWdlIG9mIHBpZ2VvbnMgZm9yYWdpbmcsIHNwbGl0IGJ5IHRoZSBhY3R1YWwgZXhwZWN0YXRpb24gb2Ygb2JzZXJ2ZXJzLg0KDQpgYGB7cn0NCg0KbmV3X2RhdGFfMiA8LSB0aWJibGUoRXhwZWN0YXRpb24gPSBjKCJIdW5ncnkiLCAiU2F0aWF0ZWQiKSkNCg0KbmV3X2RhdGFfMiAlPiUgDQogICBsZWZ0X2pvaW4oZGF0YSAlPiUgZ3JvdXBfYnkoRXhwZWN0YXRpb24pICU+JSBzdW1tYXJpc2UoYG4gb2JzZXJ2ZXJzYCA9IG4oKSkpICU+JSANCiAgY2JpbmQoZml0dGVkKGZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uLCBuZXdkYXRhID0gbmV3X2RhdGFfMiwgc3VtbWFyeSA9IFQpICU+JSANCiAgICAgICAgICBhc190aWJibGUoKSAlPiUgDQogICAgICAgICAgbXV0YXRlKGFjcm9zcygxOjQsIH4gLnggKjEwMCksDQogICAgICAgICAgICAgICAgIGFjcm9zcygxOjQsIHJvdW5kLCAyKSkpICU+JSAgDQogIHJlbmFtZSgiRXN0aW1hdGVkIHByb3BvcnRpb24gZm9yYWdpbmciID0gRXN0aW1hdGUsDQogICAgICAgICAiSW5kaWNhdGVkIGV4cGVjdGF0aW9uIiA9IEV4cGVjdGF0aW9uKSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojIGFkZCBnZW5kZXIgcHJlZGljdGlvbnMNCg0KbmV3X2RhdGFfZ2VuZGVyXzIgPC0gZXhwYW5kX2dyaWQoRXhwZWN0YXRpb24gPSBjKCJIdW5ncnkiLCAiU2F0aWF0ZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5kZXIgPSBjKCJXb21hbiIsICJNYW4iKSkNCg0KbmV3X2RhdGFfZ2VuZGVyXzIgJT4lIA0KICBsZWZ0X2pvaW4oZGF0YSAlPiUgZ3JvdXBfYnkoRXhwZWN0YXRpb24sIEdlbmRlcikgJT4lIHN1bW1hcmlzZShgbiBvYnNlcnZlcnNgID0gbigpKSAlPiUgDQogICAgICAgICAgdW5ncm91cCgpICU+JSBmaWx0ZXIoIWlzLm5hKEdlbmRlcikpKSAlPiUNCiAgY2JpbmQoZml0dGVkKGZvcmFnaW5nX21vZGVsX2V4cGVjdGF0aW9uX2dlbmRlciwgDQogICAgICAgICAgICAgICBuZXdkYXRhID0gbmV3X2RhdGFfZ2VuZGVyXzIsIHN1bW1hcnkgPSBUKSAlPiUgDQogICAgICAgICAgYXNfdGliYmxlKCkgJT4lIA0KICAgICAgICAgIG11dGF0ZShhY3Jvc3MoMTo0LCB+IC54ICoxMDApLA0KICAgICAgICAgICAgICAgICBhY3Jvc3MoMTo0LCByb3VuZCwgMikpKSAlPiUgDQogIHJlbmFtZSgiRXN0aW1hdGVkIHByb3BvcnRpb24gZm9yYWdpbmciID0gRXN0aW1hdGUsDQogICAgICAgICAiSW5kaWNhdGVkIGV4cGVjdGF0aW9uIiA9IEV4cGVjdGF0aW9uKSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KYGBgDQoNCg0KJH4kDQoNCiMjIEJ1aWxkIEZpZ3VyZSAxYS1kDQoNCiR+JA0KDQoqKkdldCBwb3N0ZXJpb3IgbWVhbnMgYW5kIGRpZmZlcmVuY2UgY29udHJhc3RzKioNCg0KYGBge3J9DQoNCiMgdHJlYXRtZW50IG1vZGVsDQoNCmRyYXdzX3RyZWF0bWVudCA8LQ0KICBhc19kcmF3c19kZihmb3JhZ2luZ19tb2RlbF90cmVhdG1lbnQpICU+JSANCiAgbXV0YXRlKEh1bmdyeSA9IGludl9sb2dpdF9zY2FsZWQoYl9CaWFzX3RyZWF0bWVudEh1bmdyeSkgKjEwMCwNCiAgICAgICAgIFNhdGlhdGVkID0gaW52X2xvZ2l0X3NjYWxlZChiX0JpYXNfdHJlYXRtZW50U2F0aWF0ZWQpKjEwMCwNCiAgICAgICAgIGRpZmZfY29udHJhc3QgPSAoSHVuZ3J5IC0gU2F0aWF0ZWQpKSAlPiUgDQogIHNlbGVjdChIdW5ncnksIFNhdGlhdGVkLCBkaWZmX2NvbnRyYXN0KSAlPiUgDQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJUcmVhdG1lbnQiLCB2YWx1ZXNfdG8gPSAiUG9zdGVyaW9yX2VzdGltYXRlIiwgY29scyA9IDE6MykgJT4lIA0KICBtdXRhdGUoUHJlZGljdG9yID0gIkFsbG9jYXRlZCBwcmltZXIiKQ0KDQpwMiA8LSANCiAgZHJhd3NfdHJlYXRtZW50ICU+JSANCiAgZmlsdGVyKFRyZWF0bWVudCAhPSAiZGlmZl9jb250cmFzdCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gUG9zdGVyaW9yX2VzdGltYXRlKSkgKyANCiAgc3RhdF9oYWxmZXllKGFlcyhmaWxsID0gVHJlYXRtZW50KSwgLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSA0LCBzdHJva2UgPSAxLjUpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMikpICsNCiAgY29vcmRfZmxpcCh5bGltID0gYygyNSwgNTUpKSArDQogICNnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIpICsNCiAgI3NjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKCwgMCwgMSkpICsNCiAgeGxhYigiQWxsb2NhdGVkIHByaW1lciIpICsNCiAgeWxhYigiRXN0aW1hdGVkICUgcGlnZW9ucyBmb3JhZ2luZyIpICsNCiAgdGhlbWVfYncoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCg0KcDMgPC0NCiAgZHJhd3NfdHJlYXRtZW50ICU+JSANCiAgZmlsdGVyKFRyZWF0bWVudCA9PSAiZGlmZl9jb250cmFzdCIpICU+JSANCiAgZ2dwbG90KGFlcyh5ID0gUG9zdGVyaW9yX2VzdGltYXRlKSkgKyANCiAgIHN0YXRfaGFsZmV5ZShhZXMoZmlsbCA9IFRyZWF0bWVudCksIC53aWR0aCA9IGMoMC42NiwgMC45NSksIGFscGhhID0gMC45LA0KICAgICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gNCwgc3Ryb2tlID0gMS41LCBzY2FsZSA9MC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIpWzRdKSArDQogIGNvb3JkX2ZsaXAoeWxpbSA9IGMoLTIwLCAyMCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjc1KSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoTlVMTCkgKw0KICB5bGFiKCJIdW5ncnkgLSBTYXRpYXRlZCBkaWZmZXJlbmNlXG5jb250cmFzdCAoJSBwb2ludHMpIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCiMgZXhwZWN0YXRpb24gbW9kZWwNCg0KZHJhd3NfZXhwZWN0YXRpb24gPC0NCiAgYXNfZHJhd3NfZGYoZm9yYWdpbmdfbW9kZWxfZXhwZWN0YXRpb24pICU+JSANCiAgbXV0YXRlKEh1bmdyeSA9IGludl9sb2dpdF9zY2FsZWQoYl9FeHBlY3RhdGlvbkh1bmdyeSkgKjEwMCwNCiAgICAgICAgIFNhdGlhdGVkID0gaW52X2xvZ2l0X3NjYWxlZChiX0V4cGVjdGF0aW9uU2F0aWF0ZWQpKjEwMCwNCiAgICAgICAgIGRpZmZfY29udHJhc3QgPSAoSHVuZ3J5IC0gU2F0aWF0ZWQpKSAlPiUgDQogIHNlbGVjdChIdW5ncnksIFNhdGlhdGVkLCBkaWZmX2NvbnRyYXN0KSAlPiUgDQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJUcmVhdG1lbnQiLCB2YWx1ZXNfdG8gPSAiUG9zdGVyaW9yX2VzdGltYXRlIiwgY29scyA9IDE6MykgJT4lIA0KICBtdXRhdGUoUHJlZGljdG9yID0gIkluZGljYXRlZCBleHBlY3RhdGlvbiIpDQoNCnA0IDwtDQogIGRyYXdzX2V4cGVjdGF0aW9uICU+JSANCiAgZmlsdGVyKFRyZWF0bWVudCAhPSAiZGlmZl9jb250cmFzdCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gUG9zdGVyaW9yX2VzdGltYXRlKSkgKyANCiAgIHN0YXRfaGFsZmV5ZShhZXMoZmlsbCA9IFRyZWF0bWVudCksIC53aWR0aCA9IGMoMC42NiwgMC45NSksIGFscGhhID0gMC45LA0KICAgICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gNCwgc3Ryb2tlID0gMS41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIsIDIpKSArDQogIGNvb3JkX2ZsaXAoeWxpbSA9IGMoMjUsIDU1KSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoIkluZGljYXRlZCBleHBlY3RhdGlvbiIpICsNCiAgeWxhYigiRXN0aW1hdGVkICUgcGlnZW9ucyBmb3JhZ2luZyIpICsNCiAgdGhlbWVfYncoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCg0KcDUgPC0NCiAgZHJhd3NfZXhwZWN0YXRpb24gJT4lIA0KICBmaWx0ZXIoVHJlYXRtZW50ID09ICJkaWZmX2NvbnRyYXN0IikgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBQb3N0ZXJpb3JfZXN0aW1hdGUpKSArIA0KICAgIHN0YXRfaGFsZmV5ZShhZXMoZmlsbCA9IFRyZWF0bWVudCksIC53aWR0aCA9IGMoMC42NiwgMC45NSksIGFscGhhID0gMC45LA0KICAgICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gNCwgc3Ryb2tlID0gMS41LCBzY2FsZSA9MC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIpWzRdKSArDQogIGNvb3JkX2ZsaXAoeWxpbSA9IGMoLTIwLCAyMCkpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjc1KSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoTlVMTCkgKw0KICB5bGFiKCJIdW5ncnkgLSBTYXRpYXRlZCBkaWZmZXJlbmNlXG5jb250cmFzdCAoJSBwb2ludHMpIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQoNCiMgdHJlYXRtZW50IG1vZGVsDQoNCmdlbmRlcl90cmVhdG1lbnRfZHJhd3MgPC0NCiAgZml0dGVkKGZvcmFnaW5nX21vZGVsX3RyZWF0bWVudF9nZW5kZXIsIA0KICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlciwgc3VtbWFyeSA9IEYpICU+JSANCiAgYXNfdGliYmxlKCkgJT4lIA0KICByZW5hbWUoSHVuZ3J5X1dvbWVuID0gVjEsIEh1bmdyeV9NZW4gPSBWMiwgU2F0aWF0ZWRfV29tZW4gPSBWMywgU2F0aWF0ZWRfTWVuID0gVjQpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjQsIG5hbWVzX3RvID0gIkdyb3VwIiwgdmFsdWVzX3RvID0gIlBvc3Rlcmlvcl9lc3RpbWF0ZSIpICU+JSANCiAgc2VwYXJhdGUoc2VwID0gIl8iLCBjb2wgPSBHcm91cCwgaW50byA9IGMoIlRyZWF0bWVudCIsICJHZW5kZXIiKSkgJT4lDQogIG11dGF0ZShQb3N0ZXJpb3JfZXN0aW1hdGUgPSBQb3N0ZXJpb3JfZXN0aW1hdGUqMTAwKSANCiAgDQpjYWxjdWxhdGVfYWxsX3RoZV9kaWZmcyA8LQ0KICBmaXR0ZWQoZm9yYWdpbmdfbW9kZWxfdHJlYXRtZW50X2dlbmRlciwgDQogICAgICAgICBuZXdkYXRhID0gbmV3X2RhdGFfZ2VuZGVyLCBzdW1tYXJ5ID0gRikgJT4lIA0KICBhc190aWJibGUoKSAlPiUgDQogIHJlbmFtZShIdW5ncnlfV29tYW4gPSBWMSwgSHVuZ3J5X01hbiA9IFYyLCBTYXRpYXRlZF9Xb21hbiA9IFYzLCBTYXRpYXRlZF9NYW4gPSBWNCkgJT4lIA0KICBtdXRhdGUoV29tYW5faF9zX2RpZmYgPSBIdW5ncnlfV29tYW4gLSBTYXRpYXRlZF9Xb21hbiwNCiAgICAgICAgIE1hbl9oX3NfZGlmZiA9IEh1bmdyeV9NYW4gLSBTYXRpYXRlZF9NYW4sDQogICAgICAgICBkaWZmX2RpZmYgPSBXb21hbl9oX3NfZGlmZiAtIE1hbl9oX3NfZGlmZikgJT4lIA0KICBzZWxlY3QoY29udGFpbnMoImRpZmYiKSkgJT4lDQogIHJlbmFtZShgSC1TICh3b21lbilgID0gV29tYW5faF9zX2RpZmYsDQogICAgICAgICBgSC1TIChtZW4pYCA9IE1hbl9oX3NfZGlmZiwNCiAgICAgICAgIGBJbnRlcmFjdGlvbmAgPSBkaWZmX2RpZmYpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjMsIG5hbWVzX3RvID0gImRpZmZfY29udHJhc3QiLCB2YWx1ZXNfdG8gPSAicG9zdGVyaW9yX2RpZmYiKSAlPiUgDQogIG11dGF0ZShwb3N0ZXJpb3JfZGlmZiA9IHBvc3Rlcmlvcl9kaWZmKjEwMCkNCiAgDQoNCmdwMSA8LSANCiAgZ2VuZGVyX3RyZWF0bWVudF9kcmF3cyAlPiUgDQogIGdncGxvdChhZXMoeCA9IEdlbmRlciwgeSA9IFBvc3Rlcmlvcl9lc3RpbWF0ZSkpICsgDQogICAgc3RhdF9zbGFiKGFscGhhID0gMC44LCBzaGFwZSA9IDIxLCBhZXMoZmlsbCA9IFRyZWF0bWVudCkpICsNCiAgI3N0YXRfaGFsZmV5ZSgud2lkdGggPSBjKDAuNjYsIDAuOTUpLCBhbHBoYSA9IDAuOSwNCiAgICMgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICMgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gNCwgc3Ryb2tlID0gMS41LA0KICAgIyAgICAgICAgICAgIGZpbGwgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCA1KVsyXSkgKw0KICAjc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMikpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAxMClbNF0sIG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIsIDEwKVs2XSkpICsNCiAgY29vcmRfZmxpcCgpKyN5bGltID0gYygyNSwgNTUpKSArDQogICNnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIpICsNCiAgI3NjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKCwgMCwgMSkpICsNCiAgbGFicyh4ID0gIkdlbmRlciIsIHkgPSAiRXN0aW1hdGVkICUgcGlnZW9ucyBmb3JhZ2luZyIsIGZpbGwgPSAiQWxsb2NhdGVkXG5wcmltZXIiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpDQoNCg0KDQpncDIgPC0NCiAgY2FsY3VsYXRlX2FsbF90aGVfZGlmZnMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkaWZmX2NvbnRyYXN0LCB5ID0gcG9zdGVyaW9yX2RpZmYpKSArIA0KICAgICNzdGF0X3NsYWIoYWxwaGEgPSAwLjksIHNoYXBlID0gMjEsIGFlcyhmaWxsID0gR2VuZGVyKSkgKw0KICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSAzLCBzdHJva2UgPSAxLjUsDQogICAgICAgICAgICAgICBmaWxsID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMTApWzVdKSArDQogICNzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICBjb29yZF9mbGlwKCkrI3lsaW0gPSBjKDI1LCA1NSkpICsNCiAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgbGluZXdpZHRoID0gMC43NSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoIkRpZmZlcmVuY2UgY29udHJhc3QiKSArDQogIHlsYWIoIiUgcG9pbnRzIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQ0KDQojIGV4cGVjdGF0aW9uIG1vZGVsDQoNCmdlbmRlcl9leHBlY3RhdGlvbl9kcmF3cyA8LQ0KICBmaXR0ZWQoZm9yYWdpbmdfbW9kZWxfZXhwZWN0YXRpb25fZ2VuZGVyLCANCiAgICAgICAgIG5ld2RhdGEgPSBuZXdfZGF0YV9nZW5kZXJfMiwgc3VtbWFyeSA9IEYpICU+JSANCiAgYXNfdGliYmxlKCkgJT4lIA0KICByZW5hbWUoSHVuZ3J5X1dvbWVuID0gVjEsIEh1bmdyeV9NZW4gPSBWMiwgU2F0aWF0ZWRfV29tZW4gPSBWMywgU2F0aWF0ZWRfTWVuID0gVjQpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjQsIG5hbWVzX3RvID0gIkdyb3VwIiwgdmFsdWVzX3RvID0gIlBvc3Rlcmlvcl9lc3RpbWF0ZSIpICU+JSANCiAgc2VwYXJhdGUoc2VwID0gIl8iLCBjb2wgPSBHcm91cCwgaW50byA9IGMoIlRyZWF0bWVudCIsICJHZW5kZXIiKSkgJT4lDQogIG11dGF0ZShQb3N0ZXJpb3JfZXN0aW1hdGUgPSBQb3N0ZXJpb3JfZXN0aW1hdGUqMTAwKSANCiAgDQpjYWxjdWxhdGVfYWxsX3RoZV9kaWZmc18yIDwtDQogIGZpdHRlZChmb3JhZ2luZ19tb2RlbF9leHBlY3RhdGlvbl9nZW5kZXIsIA0KICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlcl8yLCBzdW1tYXJ5ID0gRikgJT4lIA0KICBhc190aWJibGUoKSAlPiUgDQogIHJlbmFtZShIdW5ncnlfV29tYW4gPSBWMSwgSHVuZ3J5X01hbiA9IFYyLCBTYXRpYXRlZF9Xb21hbiA9IFYzLCBTYXRpYXRlZF9NYW4gPSBWNCkgJT4lIA0KICBtdXRhdGUoV29tYW5faF9zX2RpZmYgPSBIdW5ncnlfV29tYW4gLSBTYXRpYXRlZF9Xb21hbiwNCiAgICAgICAgIE1hbl9oX3NfZGlmZiA9IEh1bmdyeV9NYW4gLSBTYXRpYXRlZF9NYW4sDQogICAgICAgICBkaWZmX2RpZmYgPSBXb21hbl9oX3NfZGlmZiAtIE1hbl9oX3NfZGlmZikgJT4lIA0KICBzZWxlY3QoY29udGFpbnMoImRpZmYiKSkgJT4lDQogIHJlbmFtZShgSC1TICh3b21lbilgID0gV29tYW5faF9zX2RpZmYsDQogICAgICAgICBgSC1TIChtZW4pYCA9IE1hbl9oX3NfZGlmZiwNCiAgICAgICAgIGBJbnRlcmFjdGlvbmAgPSBkaWZmX2RpZmYpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjMsIG5hbWVzX3RvID0gImRpZmZfY29udHJhc3QiLCB2YWx1ZXNfdG8gPSAicG9zdGVyaW9yX2RpZmYiKSAlPiUgDQogIG11dGF0ZShwb3N0ZXJpb3JfZGlmZiA9IHBvc3Rlcmlvcl9kaWZmKjEwMCkNCg0KZ3AzIDwtIA0KICBnZW5kZXJfZXhwZWN0YXRpb25fZHJhd3MgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBQb3N0ZXJpb3JfZXN0aW1hdGUpKSArIA0KICAgIHN0YXRfc2xhYihhbHBoYSA9IDAuOSwgc2hhcGUgPSAyMSwgYWVzKGZpbGwgPSBUcmVhdG1lbnQpKSArDQogICNzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAjICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAjICAgICAgICAgICAgc2hhcGUgPSAyMSwgcG9pbnRfc2l6ZSA9IDQsIHN0cm9rZSA9IDEuNSwNCiAgICMgICAgICAgICAgICBmaWxsID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgNSlbMl0pICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMikpICsNCiAgY29vcmRfZmxpcCgpKyN5bGltID0gYygyNSwgNTUpKSArDQogICNnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIpICsNCiAgI3NjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKCwgMCwgMSkpICsNCiAgbGFicyh4ID0gIkdlbmRlciIsIHkgPSAiRXN0aW1hdGVkICUgcGlnZW9ucyBmb3JhZ2luZyIsIGZpbGwgPSAiSW5kaWNhdGVkXG5leHBlY3RhdGlvbiIpICsNCiAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KDQoNCg0KZ3A0IDwtDQogIGNhbGN1bGF0ZV9hbGxfdGhlX2RpZmZzXzIgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkaWZmX2NvbnRyYXN0LCB5ID0gcG9zdGVyaW9yX2RpZmYpKSArIA0KICAgICNzdGF0X3NsYWIoYWxwaGEgPSAwLjksIHNoYXBlID0gMjEsIGFlcyhmaWxsID0gR2VuZGVyKSkgKw0KICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSAzLCBzdHJva2UgPSAxLjUsDQogICAgICAgICAgICAgICBmaWxsID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMTApWzVdKSArDQogICNzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICBjb29yZF9mbGlwKCkrI3lsaW0gPSBjKDI1LCA1NSkpICsNCiAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgbGluZXdpZHRoID0gMC43NSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoIkRpZmZlcmVuY2UgY29udHJhc3QiKSArDQogIHlsYWIoIiUgcG9pbnRzIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQ0KDQpgYGANCg0KJH4kDQoNCiMgUXVlc3Rpb24gMjogaXMgZXN0aW1hdGlvbiBvZiBmZWVkaW5nIHJhdGUgYWZmZWN0ZWQgYnkgYmlhcyBtYW5pcHVsYXRpb25zPw0KDQokfiQNCg0KV2UgYXNrZWQgb2JzZXJ2ZXJzIHRvIGNvdW50IHRoZSBudW1iZXIgb2YgcGVja3Mgb2YgdGhlIGdyb3VuZCB0aGF0IGEgc2VsZWN0ZWQgcGlnZW9uIG1hZGUgb3ZlciBhIDEgbWludXRlIHBlcmlvZC4gV2UgdXNlIHRoZSBudW1iZXIgb2YgcGVja3MgdGhhdCBvY2N1ciBhcyBhIG1lYXN1cmUgb2YgZmVlZGluZyByYXRlLg0KDQpXZSBmaXJzdCBlc3RpbWF0ZWQgYSBiYXNlbGluZSBwZWNrIHJhdGUgYnkgb2JzZXJ2aW5nIDM1IHBpZ2VvbnMuIFRvIHNlbGVjdCB0aGUgcGlnZW9ucyB3ZSBvYnNlcnZlZCwgd2Ugc3BsaXQgYSBzdGlsbCBpbWFnZSBvZiB0aGUgZm9yYWdpbmcgdmlkZW8gKHRha2VuIGF0IHRpbWUgemVybykgaW50byBhIDQzIHggMjEgY2VsbCBncmlkLiBGcm9tIHRoZSAxMjIgY2VsbHMgdGhhdCBjb250YWluZWQgcGlnZW9ucywgNDAgd2VyZSBjaG9zZW4gYnkgcmFuZG9tIG51bWJlciBnZW5lcmF0aW9uIChzZWUgY29kZSBjaHVuayBiZWxvdykuIEluIHRoZSBldmVudCB0aGF0IG11bHRpcGxlIHBpZ2VvbnMgd2VyZSBwcmVzZW50IGluIHRoZSBjZWxsLCB3ZSBzZWxlY3RlZCB0aGUgbW9zdCBwcm9taW5lbnQgdG8gb2JzZXJ2ZS4gRml2ZSBvYnNlcnZhdGlvbnMgd2VyZSBkaXNjYXJkZWQgLSB0aHJlZSBkdWUgdG8gb3ZlcmxhcCBvZiB0aGUgc2FtZSBwaWdlb24gYmV0d2VlbiBjZWxscyB0aGF0IHdlcmUgc2VsZWN0ZWQgYnkgdGhlIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yLCBhbmQgdHdvIG1vcmUgYXMgdGhlIHBpZ2VvbnMgbGVmdCB0aGUgZmllbGQgb2YgdmlldyBkdXJpbmcgdGhlIHZpZGVvIGFuZCBjb3VsZCBubyBsb25nZXIgYmUgdHJhY2tlZC4gDQoNCg0KYGBge3J9DQojIGN1cmx5IGJyYWNrZXRzIHJ1biBhbGwgbGluZXMgaW5jbHVkZWQgd2l0aGluIHRoZW0NCg0Ke3NldC5zZWVkKDEpICMgc28gdGhhdCBzYW1wbGUgcHJvZHVjZXMgYSByZXByb2R1Y2libGUgc2VxdWVuY2UgDQogIHNhbXBsZSgxOjEyMiwgNDAsIHJlcGxhY2UgPSBGQUxTRSl9DQpgYGANCg0KVGhlIHNlbGVjdGVkIHBpZ2VvbnMgZm9yIGJhc2VsaW5lIG9ic2VydmF0aW9uIGFyZSBzaG93biBpbiB0aGUgaW1hZ2UgYmVsb3cNCg0KYGBge3J9DQppbWcgPC0gcmVhZFBORygicGlnZW9uX3NlbGVjdGlvbi5wbmciKQ0KIGdyaWQucmFzdGVyKGltZykNCmBgYA0KDQoNCiR+JA0KDQojIyBFc3RpbWF0aW5nIGJhc2VsaW5lIGZlZWRpbmcgcmF0ZQ0KDQokfiQNCg0KKipMb2FkIGluIHRoZSBkYXRhKioNCg0KYGBge3J9DQoNCmJhc2VsaW5lX2RhdGEgPC0gcmVhZF9jc3YoImRhdGEvYmFzZWxpbmVfcGVja19kYXRhLmNzdiIpICU+JSANCiAgc2VsZWN0KDE6NSkgJT4lICAjIHJlbW92ZSB0aGUgY29tbWVudHMgY29sdW1uDQogIHBpdm90X2xvbmdlcihjb2xzID0gNDo1LCBuYW1lc190byA9ICJPYnNlcnZhdGlvbiIsIHZhbHVlc190byA9ICJQZWNrX3JhdGUiKSAlPiUgDQogIG11dGF0ZShJRCA9IGFzLmZhY3RvcihJRCksDQogICAgICAgICBPYnNlcnZhdGlvbiA9IHN0cl9yZW1vdmUoT2JzZXJ2YXRpb24sICJQZWNrX2NvdW50XyIpKSAlPiUgDQogIHJlbmFtZShQaWdlb25fSUQgPSBJRCkgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKFBlY2tfcmF0ZSkpDQoNCm15X2RhdGFfdGFibGUgPC0gZnVuY3Rpb24oZGYpew0KICBkYXRhdGFibGUoDQogICAgZGYsIHJvd25hbWVzPUZBTFNFLA0KICAgIGF1dG9IaWRlTmF2aWdhdGlvbiA9IFRSVUUsDQogICAgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgICJCdXR0b25zIiksDQogICAgb3B0aW9ucyA9IGxpc3QoDQogICAgICBkb20gPSAnQmZydGlwJywNCiAgICAgIGRlZmVyUmVuZGVyPVRSVUUsDQogICAgICBzY3JvbGxYPVRSVUUsIHNjcm9sbFk9NDAwLA0KICAgICAgc2Nyb2xsQ29sbGFwc2U9VFJVRSwNCiAgICAgIGJ1dHRvbnMgPQ0KICAgICAgICBsaXN0KCdwYWdlTGVuZ3RoJywgJ2NvbHZpcycsICdjc3YnLCBsaXN0KA0KICAgICAgICAgIGV4dGVuZCA9ICdwZGYnLA0KICAgICAgICAgIHBhZ2VTaXplID0gJ0E0JywNCiAgICAgICAgICBvcmllbnRhdGlvbiA9ICdsYW5kc2NhcGUnLA0KICAgICAgICAgIGZpbGVuYW1lID0gJ2Jhc2VsaW5lX2RhdGFzZXQnKSksDQogICAgICBwYWdlTGVuZ3RoID0gNzgNCiAgICApDQogICkNCn0NCg0KDQpteV9kYXRhX3RhYmxlKGJhc2VsaW5lX2RhdGEpDQoNCmBgYA0KDQotIGBYYCBhbmQgYFlgIHJlcHJlc2VudCBncmlkIGNvb3JkaW5hdGVzLg0KDQotIGBQaWdlb25fSURgIGlkZW50aWZpZXMgYSBzcGVjaWZpYyBwaWdlb24NCg0KLSBgT2JzZXJ2YXRpb25gIGluZGljYXRlcyB3aGV0aGVyIHRoaXMgd2FzIHRoZSBmaXJzdCBvciBzZWNvbmQgc2NvcmluZyBmb3IgYSBzaW5nbGUgcGlnZW9uLiBXZSBzY29yZWQgZWFjaCBwaWdlb24gdHdpY2UgYXMgZGlzdGFudCBwaWdlb25zIHdlcmUgZGlmZmljdWx0IHRvIG9ic2VydmUgYW5kIHRvIGVuc3VyZSB0aGF0IHRoZSBjb3JyZWN0IHBpZ2VvbiB3YXMgdHJhY2tlZCB0aHJvdWdob3V0IHRoZSBtaW51dGUgb2Ygb2JzZXJ2YXRpb24uDQoNCi0gYFBlY2tfcmF0ZWAgaXMgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUgZ3JvdW5kIHdhcyBwZWNrZWQgb3ZlciBhIG1pbnV0ZSBvZiBvYnNlcnZhdGlvbi4NCg0KJH4kDQoNCioqRml0IGEgc2ltcGxlIG1vZGVsIHRvIGVzdGltYXRlIG1lZGlhbiBwZWNrIHJhdGUqKg0KDQpgYGB7cn0NCg0KYmFzZWxpbmVfcGVja19tb2RlbF96aSA8LQ0KICBicm0oUGVja19yYXRlIH4gMSArICgxfFBpZ2Vvbl9JRCksDQogICAgICBmYW1pbHkgPSB6ZXJvX2luZmxhdGVkX25lZ2Jpbm9taWFsKCksIGRhdGEgPSBiYXNlbGluZV9kYXRhLA0KICAgICAgcHJpb3IgPSBjKCBwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBJbnRlcmNlcHQpLA0KICAgICAgICAgICAgICAgICBwcmlvcihleHBvbmVudGlhbCgxKSwgY2xhc3MgPSBzZCksDQogICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHNoYXBlKSwNCiAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gemkpKSwNCiAgICAgIGNoYWlucyA9IDQsIGNvcmVzID0gNCwgd2FybXVwID0gMjAwMCwgaXRlciA9IDYwMDAsDQogICAgICBmaWxlID0gImZpdHMvYmFzZWxpbmVfcGVja19tb2RlbCIpDQoNCiMgd3JhbmdsZSB0aGUgb3V0cHV0DQoNCmJhc2VsaW5lX3BlY2tfcHJlZGljdGlvbnMgPC0NCiAgYmFzZWxpbmVfcGVja19tb2RlbF96aSAlPiUgDQogIGFzX2RyYXdzX2RmKCkgJT4lIA0KICBtdXRhdGUoQmFzZWxpbmVfZXN0aW1hdGUgPSBleHAoYl9JbnRlcmNlcHQpLA0KICAgICAgICAgcGVja19yYXRlX3NkID0gZXhwKHNkX1BpZ2Vvbl9JRF9fSW50ZXJjZXB0KSkgJT4lIA0KICBzZWxlY3QoQmFzZWxpbmVfZXN0aW1hdGUsIHBlY2tfcmF0ZV9zZCkNCg0KYmFzZWxpbmVfZGF0YSAlPiUgDQogIGRpc3RpbmN0KFBpZ2Vvbl9JRCkgJT4lIA0KICBzdW1tYXJpc2UoYG4gcGlnZW9ucyBvYnNlcnZlZGAgPSBsZW5ndGgoUGlnZW9uX0lEKSkgJT4lDQogIGJpbmRfY29scygNCmZpdHRlZChiYXNlbGluZV9wZWNrX21vZGVsX3ppLCBzdW1tYXJ5ID0gVCwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogICAgICAgICAgYXNfdGliYmxlKCkgJT4lDQogICAgICAgICAgZGlzdGluY3QoRXN0aW1hdGUsIC5rZWVwX2FsbCA9IFQpICU+JSANCiAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSAlPiUgDQogIHJlbmFtZShgQmFzZWxpbmUgbWVkaWFuIHBlY2sgcmF0ZSAvIHBlciBtaW5gID0gRXN0aW1hdGUpKSAlPiUNCiAgcGFuZGVyKCkNCg0KYGBgDQoNCiR+JA0KDQojIyBFeHBlcmltZW50YWwgZGF0YQ0KDQokfiQNCg0KIyMjIEV4cGxvcmluZyBhbGxvY2F0aW9uIHZlcnN1cyBleHBlY3RhdGlvbiAyLjAgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KJH4kDQoNCk9uY2UgYWdhaW4sIHdlIGV4cGVjdCB0aGF0IGF0dGVudGlvbiBwYWlkIHRvIGFuZC9vciBjb21wcmVoZW5zaW9uIG9mIHRoZSBwcmltZXIgc3RhdGVtZW50IGhhcyBhIGxhcmdlIGVmZmVjdCBvbiBvYnNlcnZlcnMnIHBlcmNlcHRpb24gb2YgcGlnZW9uIGZvcmFnaW5nLiANCg0KTGV0cyBhZ2FpbiBmaXQgb3VyIHR3byBtb2RlbHM6DQoNCjEuIGEgbW9kZWwgd2l0aCBhbGxvY2F0ZWQgcHJpbWVyIChgQmlhc190cmVhdG1lbnRgKSBhcyB0aGUgcHJlZGljdG9yIHZhcmlhYmxlIA0KDQoyLiBhIG1vZGVsIHdpdGggaW5kaWNhdGVkIGh1bmdlciBleHBlY3RhdGlvbiAoYEV4cGVjdGF0aW9uYCkgYXMgdGhlIHByZWRpY3RvciB2YXJpYWJsZQ0KDQokfiQNCg0KIyMjIyBNb2RlbCAxOiBhbGxvY2F0ZWQgcHJpbWVyDQoNCmBgYHtyfQ0KDQojIEZpcnN0IGxldCdzIG1vZGVsIHRoZSBlZmZlY3Qgb2YgYmlhcyB0cmVhdG1lbnQgb24gcGVjayByYXRlDQoNCnBlY2tfbW9kZWxfdHJlYXRtZW50IDwtIA0KICBicm0oUGVja19yYXRlIH4gMCArIEJpYXNfdHJlYXRtZW50ICsgKDF8T2JzZXJ2ZXJfSUQpLA0KICAgICAgZGF0YSA9IGRhdGFfcGVjaywgZmFtaWx5ID0gbmVnYmlub21pYWwsDQogICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gc2QpKSwNCiAgICAgIGl0ZXIgPSA2MDAwLCB3YXJtdXAgPSAyMDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQsDQogICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOSwgbWF4X3RyZWVkZXB0aCA9IDEyKSwNCiAgICAgIHNlZWQgPSAxLCBmaWxlID0gImZpdHMvcGVja19tb2RlbF90cmVhdG1lbnQiKQ0KDQpwZWNrX21vZGVsX3RyZWF0bWVudCA8LSBhZGRfY3JpdGVyaW9uKHBlY2tfbW9kZWxfdHJlYXRtZW50LCBjcml0ZXJpb24gPSAibG9vIiwgZmlsZSA9ICJmaXRzL3BlY2tfbW9kZWxfdHJlYXRtZW50IikNCiAgDQpwZWNrX21vZGVsX3RyZWF0bWVudA0KDQpwZWNrX21vZGVsX3RyZWF0bWVudF9nZW5kZXIgPC0gDQogIGJybShQZWNrX3JhdGUgfiAwICsgR2VuZGVyICogQmlhc190cmVhdG1lbnQgKyAoMXxPYnNlcnZlcl9JRCksDQogICAgICBkYXRhID0gZGF0YV9wZWNrLCBmYW1pbHkgPSBuZWdiaW5vbWlhbCwNCiAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBiKSwNCiAgICAgICAgICAgICAgICBwcmlvcihleHBvbmVudGlhbCgxKSwgY2xhc3MgPSBzZCkpLA0KICAgICAgaXRlciA9IDYwMDAsIHdhcm11cCA9IDIwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45LCBtYXhfdHJlZWRlcHRoID0gMTIpLA0KICAgICAgc2VlZCA9IDEsIGZpbGUgPSAiZml0cy9wZWNrX21vZGVsX3RyZWF0bWVudF9nZW5kZXIiKQ0KYGBgDQoNCioqVGFibGUgUzMqKi4gVGhlIGVzdGltYXRlZCBwZWNrIHJhdGUgb2YgZm9yYWdpbmcgcGlnZW9ucywgc3BsaXQgYnkgdGhlIHByaW1lciBvYnNlcnZlcnMgd2VyZSBhbGxvY2F0ZWQuDQoNCmBgYHtyfQ0KbmV3X2RhdGEgJT4lIA0KICBiaW5kX2NvbHMoZml0dGVkKHBlY2tfbW9kZWxfdHJlYXRtZW50LCBuZXdkYXRhID0gbmV3X2RhdGEsIHN1bW1hcnkgPSBULCByZV9mb3JtdWxhID0gTkEpICU+JSANCiAgICAgICAgICAgICAgYXNfdGliYmxlKCkgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSkgJT4lIA0KICBsZWZ0X2pvaW4oZGF0YV9wZWNrICU+JSBncm91cF9ieShCaWFzX3RyZWF0bWVudCkgJT4lIA0KICAgICAgICAgICAgICBkaXN0aW5jdChPYnNlcnZlcl9JRCkgJT4lIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IG4oKSkpICU+JSANCiAgcmVuYW1lKCJFc3RpbWF0ZWQgcGVjayByYXRlIiA9IEVzdGltYXRlLA0KICAgICAgICAgIkJpYXMgdHJlYXRtZW50IiA9IEJpYXNfdHJlYXRtZW50KSAlPiUgDQogIGJpbmRfcm93cyhmaXR0ZWQoYmFzZWxpbmVfcGVja19tb2RlbF96aSwgc3VtbWFyeSA9IFQsIHJlX2Zvcm11bGEgPSBOQSkgJT4lIA0KICAgICAgICAgICAgICBhc190aWJibGUoKSAlPiUNCiAgICAgICAgICAgICAgZGlzdGluY3QoRXN0aW1hdGUsIC5rZWVwX2FsbCA9IFQpICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGFjcm9zcygxOjQsIHJvdW5kLCAyKSkgJT4lIA0KICAgICAgICAgICAgICByZW5hbWUoIkVzdGltYXRlZCBwZWNrIHJhdGUiID0gRXN0aW1hdGUpICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGBCaWFzIHRyZWF0bWVudGAgPSAiQmFzZWxpbmUiKSAlPiUgDQogICAgICAgICAgICAgIGJpbmRfY29scyhiYXNlbGluZV9kYXRhICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3QoUGlnZW9uX0lEKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IGxlbmd0aChQaWdlb25fSUQpKSkpICU+JSANCiAgc2VsZWN0KGBCaWFzIHRyZWF0bWVudGAsIGBuIHBpZ2VvbnMgb2JzZXJ2ZWRgLCBldmVyeXRoaW5nKCkpICU+JSANCiAgcGFuZGVyKHNwbGl0LmNlbGwgPSAyMCwgc3BsaXQudGFibGUgPSBJbmYpDQoNCmBgYA0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCiMgYWRkIHRoZSBnZW5kZXIgdGFibGUNCg0KbmV3X2RhdGFfZ2VuZGVyICU+JSANCiAgYmluZF9jb2xzKGZpdHRlZChwZWNrX21vZGVsX3RyZWF0bWVudF9nZW5kZXIsIA0KICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlciwgc3VtbWFyeSA9IFQsIHJlX2Zvcm11bGEgPSBOQSkgJT4lIA0KICAgICAgICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSkgJT4lIA0KICBsZWZ0X2pvaW4oZGF0YV9wZWNrICU+JSBncm91cF9ieShCaWFzX3RyZWF0bWVudCwgR2VuZGVyKSAlPiUgDQogICAgICAgICAgICAgICBkaXN0aW5jdChPYnNlcnZlcl9JRCkgJT4lIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IG4oKSkpICU+JSANCiAgICByZW5hbWUoIkVzdGltYXRlZCBwZWNrIHJhdGUiID0gRXN0aW1hdGUsDQogICAgICAgICAiQmlhcyB0cmVhdG1lbnQiID0gQmlhc190cmVhdG1lbnQpICU+JSANCiAgYmluZF9yb3dzKGZpdHRlZChiYXNlbGluZV9wZWNrX21vZGVsX3ppLCBzdW1tYXJ5ID0gVCwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogICAgICAgICAgICAgIGFzX3RpYmJsZSgpICU+JQ0KICAgICAgICAgICAgICBkaXN0aW5jdChFc3RpbWF0ZSwgLmtlZXBfYWxsID0gVCkgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSAlPiUgDQogICAgICAgICAgICAgIHJlbmFtZSgiRXN0aW1hdGVkIHBlY2sgcmF0ZSIgPSBFc3RpbWF0ZSkgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoYEJpYXMgdHJlYXRtZW50YCA9ICJCYXNlbGluZSIsIEdlbmRlciA9ICItIikgJT4lIA0KICAgICAgICAgICAgICBiaW5kX2NvbHMoYmFzZWxpbmVfZGF0YSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RpbmN0KFBpZ2Vvbl9JRCkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoYG4gcGlnZW9ucyBvYnNlcnZlZGAgPSBsZW5ndGgoUGlnZW9uX0lEKSkpKSAlPiUgDQogIHNlbGVjdChgQmlhcyB0cmVhdG1lbnRgLCBgbiBwaWdlb25zIG9ic2VydmVkYCwgZXZlcnl0aGluZygpKSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KYGBgDQoNCg0KIyMjIyBNb2RlbCAyOiBJbmRpY2F0ZWQgZXhwZWN0YXRpb24NCg0KYGBge3J9DQoNCiMgZml0IHRoZSBzYW1lIG1vZGVsLCBleGNlcHQgdXNpbmcgcGFydGljaXBhbnQgZXhwZWN0YXRpb24gcmF0aGVyIHRoYW4gYWxsb2NhdGVkIGJpYXMgdHJlYXRtZW50DQoNCnBlY2tfbW9kZWxfZXhwZWN0YXRpb24gPC0gYnJtKFBlY2tfcmF0ZSB+IDAgKyBFeHBlY3RhdGlvbiArICgxfE9ic2VydmVyX0lEKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV9wZWNrLCBmYW1pbHkgPSBuZWdiaW5vbWlhbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHNkKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDYwMDAsIHdhcm11cCA9IDIwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTUsIG1heF90cmVlZGVwdGggPSAxMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEsIGZpbGUgPSAiZml0cy9wZWNrX21vZGVsX2V4cGVjdGF0aW9uIikNCg0KcGVja19tb2RlbF9leHBlY3RhdGlvbiA8LSBhZGRfY3JpdGVyaW9uKHBlY2tfbW9kZWxfZXhwZWN0YXRpb24sIGNyaXRlcmlvbiA9ICJsb28iLCBmaWxlID0gImZpdHMvcGVja19tb2RlbF9leHBlY3RhdGlvbiIpDQoNCg0KcGVja19tb2RlbF9leHBlY3RhdGlvbg0KI2xvb19jb21wYXJlKHBlY2tfbW9kZWxfdHJlYXRtZW50LCBwZWNrX21vZGVsX2V4cGVjdGF0aW9uKQ0KDQpwZWNrX21vZGVsX2V4cGVjdGF0aW9uX2dlbmRlciA8LSBicm0oUGVja19yYXRlIH4gMCArIEdlbmRlciAqIEV4cGVjdGF0aW9uICsgKDF8T2JzZXJ2ZXJfSUQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3BlY2ssIGZhbWlseSA9IG5lZ2Jpbm9taWFsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gc2QpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNjAwMCwgd2FybXVwID0gMjAwMCwgY2hhaW5zID0gNCwgY29yZXMgPSA0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45NSwgbWF4X3RyZWVkZXB0aCA9IDEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMSwgZmlsZSA9ICJmaXRzL3BlY2tfbW9kZWxfZXhwZWN0YXRpb25fZ2VuZGVyIikNCmBgYA0KDQoqKlRhYmxlIFM0KiouIFRoZSBlc3RpbWF0ZWQgcGVjayByYXRlIG9mIGZvcmFnaW5nIHBpZ2VvbnMsIHNwbGl0IGJ5IHRoZSBpbmRpY2F0ZWQgZXhwZWN0YXRpb24gb2YgdGhlIG9ic2VydmVycy4NCg0KYGBge3J9DQoNCm5ld19kYXRhXzIgJT4lIA0KICBiaW5kX2NvbHMoZml0dGVkKHBlY2tfbW9kZWxfZXhwZWN0YXRpb24sIG5ld2RhdGEgPSBuZXdfZGF0YV8yLCBzdW1tYXJ5ID0gVCwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogICAgICAgICAgICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGFjcm9zcygxOjQsIHJvdW5kLCAyKSkpICU+JSANCiAgbGVmdF9qb2luKGRhdGFfcGVjayAlPiUgZ3JvdXBfYnkoRXhwZWN0YXRpb24pICU+JSANCiAgICAgICAgICAgICAgZGlzdGluY3QoT2JzZXJ2ZXJfSUQpICU+JSBzdW1tYXJpc2UoYG4gcGlnZW9ucyBvYnNlcnZlZGAgPSBuKCkpKSAlPiUgDQogIHJlbmFtZSgiRXN0aW1hdGVkIHBlY2sgcmF0ZSIgPSBFc3RpbWF0ZSwNCiAgICAgICAgICJJbmRpY2F0ZWQgZXhwZWN0YXRpb24iID0gRXhwZWN0YXRpb24pICU+JSANCiAgYmluZF9yb3dzKGZpdHRlZChiYXNlbGluZV9wZWNrX21vZGVsX3ppLCBzdW1tYXJ5ID0gVCwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogICAgICAgICAgICAgIGFzX3RpYmJsZSgpICU+JQ0KICAgICAgICAgICAgICBkaXN0aW5jdChFc3RpbWF0ZSwgLmtlZXBfYWxsID0gVCkgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSAlPiUgDQogICAgICAgICAgICAgIHJlbmFtZSgiRXN0aW1hdGVkIHBlY2sgcmF0ZSIgPSBFc3RpbWF0ZSkgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoYEluZGljYXRlZCBleHBlY3RhdGlvbmAgPSAiQmFzZWxpbmUiKSAlPiUgDQogICAgICAgICAgICAgIGJpbmRfY29scyhiYXNlbGluZV9kYXRhICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3QoUGlnZW9uX0lEKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IGxlbmd0aChQaWdlb25fSUQpKSkpICU+JSANCiAgc2VsZWN0KGBJbmRpY2F0ZWQgZXhwZWN0YXRpb25gLCBgbiBwaWdlb25zIG9ic2VydmVkYCwgZXZlcnl0aGluZygpKSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQoNCiMgYWRkIHRoZSBnZW5kZXIgdGFibGUNCg0KbmV3X2RhdGFfZ2VuZGVyXzIgJT4lIA0KICBiaW5kX2NvbHMoZml0dGVkKHBlY2tfbW9kZWxfZXhwZWN0YXRpb25fZ2VuZGVyLCANCiAgICAgICAgICAgICAgIG5ld2RhdGEgPSBuZXdfZGF0YV9nZW5kZXJfMiwgc3VtbWFyeSA9IFQsIHJlX2Zvcm11bGEgPSBOQSkgJT4lIA0KICAgICAgICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICAgICAgICBtdXRhdGUoYWNyb3NzKDE6NCwgcm91bmQsIDIpKSkgJT4lIA0KICBsZWZ0X2pvaW4oZGF0YV9wZWNrICU+JSBncm91cF9ieShFeHBlY3RhdGlvbiwgR2VuZGVyKSAlPiUgDQogICAgICAgICAgICAgICBkaXN0aW5jdChPYnNlcnZlcl9JRCkgJT4lIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IG4oKSkpICU+JSANCiAgICByZW5hbWUoIkVzdGltYXRlZCBwZWNrIHJhdGUiID0gRXN0aW1hdGUsDQogICAgICAgICAiSW5kaWNhdGVkIGV4cGVjdGF0aW9uIiA9IEV4cGVjdGF0aW9uKSAlPiUgDQogIGJpbmRfcm93cyhmaXR0ZWQoYmFzZWxpbmVfcGVja19tb2RlbF96aSwgc3VtbWFyeSA9IFQsIHJlX2Zvcm11bGEgPSBOQSkgJT4lIA0KICAgICAgICAgICAgICBhc190aWJibGUoKSAlPiUNCiAgICAgICAgICAgICAgZGlzdGluY3QoRXN0aW1hdGUsIC5rZWVwX2FsbCA9IFQpICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGFjcm9zcygxOjQsIHJvdW5kLCAyKSkgJT4lIA0KICAgICAgICAgICAgICByZW5hbWUoIkVzdGltYXRlZCBwZWNrIHJhdGUiID0gRXN0aW1hdGUpICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGBJbmRpY2F0ZWQgZXhwZWN0YXRpb25gID0gIkJhc2VsaW5lIiwgR2VuZGVyID0gIi0iKSAlPiUgDQogICAgICAgICAgICAgIGJpbmRfY29scyhiYXNlbGluZV9kYXRhICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3QoUGlnZW9uX0lEKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShgbiBwaWdlb25zIG9ic2VydmVkYCA9IGxlbmd0aChQaWdlb25fSUQpKSkpICU+JSANCiAgc2VsZWN0KGBJbmRpY2F0ZWQgZXhwZWN0YXRpb25gLCBgbiBwaWdlb25zIG9ic2VydmVkYCwgZXZlcnl0aGluZygpKSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gMjAsIHNwbGl0LnRhYmxlID0gSW5mKQ0KYGBgDQoNCg0KJH4kDQoNCiMjIyBCdWlsZCBGaWd1cmUgMWUtaA0KDQokfiQNCg0KKipHZXQgcG9zdGVyaW9yIG1lYW5zIGFuZCBkaWZmZXJlbmNlIGNvbnRyYXN0cyoqDQoNCmBgYHtyfQ0KDQojIHRyZWF0bWVudCBtb2RlbA0KDQpwZWNrX2RyYXdzX3RyZWF0bWVudCA8LQ0KICBhc19kcmF3c19kZihwZWNrX21vZGVsX3RyZWF0bWVudCkgJT4lIA0KICBtdXRhdGUoSHVuZ3J5ID0gZXhwKGJfQmlhc190cmVhdG1lbnRIdW5ncnkpLA0KICAgICAgICAgU2F0aWF0ZWQgPSBleHAoYl9CaWFzX3RyZWF0bWVudFNhdGlhdGVkKSwNCiAgICAgICAgIGRpZmZfY29udHJhc3QgPSAoSHVuZ3J5IC0gU2F0aWF0ZWQpKSAlPiUgDQogIHNlbGVjdChIdW5ncnksIFNhdGlhdGVkLCBkaWZmX2NvbnRyYXN0KSAlPiUNCiAgYmluZF9jb2xzKGJhc2VsaW5lX3BlY2tfcHJlZGljdGlvbnMgJT4lIHNlbGVjdChCYXNlbGluZV9lc3RpbWF0ZSkpICU+JSANCiAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gIlRyZWF0bWVudCIsIHZhbHVlc190byA9ICJQb3N0ZXJpb3JfZXN0aW1hdGUiLCBjb2xzID0gMTozKSAlPiUgDQogIG11dGF0ZShQcmVkaWN0b3IgPSAiQWxsb2NhdGVkIHByaW1lciIpDQoNCg0KcDYgPC0gDQogICAgcGVja19kcmF3c190cmVhdG1lbnQgJT4lIA0KICAgIGZpbHRlcihUcmVhdG1lbnQgIT0gImRpZmZfY29udHJhc3QiKSAlPiUgDQogICAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gUG9zdGVyaW9yX2VzdGltYXRlKSkgKw0KICAgIHN0YXRfc2xhYihhZXMoeSA9IEJhc2VsaW5lX2VzdGltYXRlKSwNCiAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjgsIHNsYWJfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsNCiAgICBzdGF0X2hhbGZleWUoYWVzKGZpbGwgPSBUcmVhdG1lbnQpLCAud2lkdGggPSBjKDAuNjYsIDAuOTUpLCBhbHBoYSA9IDAuOSwNCiAgICAgICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSA0LCBzdHJva2UgPSAxLjUpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICAgIGNvb3JkX2ZsaXAoeWxpbSA9IGMoMCwgMjApKSArDQogICAgI2dlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMikgKw0KICAgICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogICAgeGxhYigiQWxsb2NhdGVkIHByaW1lciIpICsNCiAgICB5bGFiKCJFc3RpbWF0ZWQgcGVja3MgcGVyIG1pbiIpICsNCiAgICB0aGVtZV9idygpICsgDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KDQpwNyA8LQ0KICBwZWNrX2RyYXdzX3RyZWF0bWVudCAlPiUgDQogIGZpbHRlcihUcmVhdG1lbnQgPT0gImRpZmZfY29udHJhc3QiKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IFBvc3Rlcmlvcl9lc3RpbWF0ZSkpICsgDQogICBzdGF0X2hhbGZleWUoYWVzKGZpbGwgPSBUcmVhdG1lbnQpLCAud2lkdGggPSBjKDAuNjYsIDAuOTUpLCBhbHBoYSA9IDAuOSwNCiAgICAgICAgICAgICAgIHBvaW50X2ludGVydmFsID0gIm1lZGlhbl9xaSIsIHBvaW50X2ZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgcG9pbnRfc2l6ZSA9IDQsIHN0cm9rZSA9IDEuNSwgc2NhbGUgPTAuNSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiKVs0XSkgKw0KICBjb29yZF9mbGlwKHlsaW0gPSBjKC01LCAxMikpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjc1KSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoTlVMTCkgKw0KICB5bGFiKCJIdW5ncnkgLSBTYXRpYXRlZCBkaWZmZXJlbmNlXG5jb250cmFzdCAocGVja3MgcGVyIG1pbikiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCg0KIyBleHBlY3RhdGlvbiBtb2RlbA0KDQpwZWNrX2RyYXdzX2V4cGVjdGF0aW9uIDwtDQogIGFzX2RyYXdzX2RmKHBlY2tfbW9kZWxfZXhwZWN0YXRpb24pICU+JSANCiAgbXV0YXRlKEh1bmdyeSA9IGV4cChiX0V4cGVjdGF0aW9uSHVuZ3J5KSwNCiAgICAgICAgIFNhdGlhdGVkID0gZXhwKGJfRXhwZWN0YXRpb25TYXRpYXRlZCksDQogICAgICAgICBkaWZmX2NvbnRyYXN0ID0gKEh1bmdyeSAtIFNhdGlhdGVkKSkgJT4lIA0KICBzZWxlY3QoSHVuZ3J5LCBTYXRpYXRlZCwgZGlmZl9jb250cmFzdCkgJT4lIA0KICBiaW5kX2NvbHMoYmFzZWxpbmVfcGVja19wcmVkaWN0aW9ucyAlPiUgc2VsZWN0KEJhc2VsaW5lX2VzdGltYXRlKSkgJT4lIA0KICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiVHJlYXRtZW50IiwgdmFsdWVzX3RvID0gIlBvc3Rlcmlvcl9lc3RpbWF0ZSIsIGNvbHMgPSAxOjMpICU+JSANCiAgbXV0YXRlKFByZWRpY3RvciA9ICJBbGxvY2F0ZWQgcHJpbWVyIikNCg0KcDggPC0NCiAgcGVja19kcmF3c19leHBlY3RhdGlvbiAlPiUgDQogIGZpbHRlcihUcmVhdG1lbnQgIT0gImRpZmZfY29udHJhc3QiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFRyZWF0bWVudCwgeSA9IFBvc3Rlcmlvcl9lc3RpbWF0ZSkpICsgDQogIHN0YXRfc2xhYihhZXMoeSA9IEJhc2VsaW5lX2VzdGltYXRlKSwNCiAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjgsIHNsYWJfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsNCiAgICBzdGF0X2hhbGZleWUoYWVzKGZpbGwgPSBUcmVhdG1lbnQpLCAud2lkdGggPSBjKDAuNjYsIDAuOTUpLCBhbHBoYSA9IDAuOSwNCiAgICAgICAgICAgICAgIHBvaW50X2ludGVydmFsID0gIm1lZGlhbl9xaSIsIHBvaW50X2ZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgcG9pbnRfc2l6ZSA9IDQsIHN0cm9rZSA9IDEuNSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICBjb29yZF9mbGlwKHlsaW0gPSBjKDAsIDIwKSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIHhsYWIoIkluZGljYXRlZCBleHBlY3RhdGlvbiIpICsNCiAgeWxhYigiRXN0aW1hdGVkIHBlY2tzIHBlciBtaW4iKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCnA5IDwtDQogIHBlY2tfZHJhd3NfZXhwZWN0YXRpb24gJT4lIA0KICBmaWx0ZXIoVHJlYXRtZW50ID09ICJkaWZmX2NvbnRyYXN0IikgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBQb3N0ZXJpb3JfZXN0aW1hdGUpKSArIA0KICAgc3RhdF9oYWxmZXllKGFlcyhmaWxsID0gVHJlYXRtZW50KSwgLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSA0LCBzdHJva2UgPSAxLjUsIHNjYWxlID0wLjUpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIilbNF0pICsNCiAgY29vcmRfZmxpcCh5bGltID0gYygtNSwgMTIpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgbGluZXdpZHRoID0gMC43NSkgKw0KICAjc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoLCAwLCAxKSkgKw0KICB4bGFiKE5VTEwpICsNCiAgeWxhYigiSHVuZ3J5IC0gU2F0aWF0ZWQgZGlmZmVyZW5jZVxuY29udHJhc3QgKHBlY2tzIHBlciBtaW4pIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojIHdpdGggZ2VuZGVyDQoNCmdlbmRlcl90cmVhdG1lbnRfZHJhd3NfMiA8LQ0KICBmaXR0ZWQocGVja19tb2RlbF90cmVhdG1lbnRfZ2VuZGVyLCANCiAgICAgICAgIG5ld2RhdGEgPSBuZXdfZGF0YV9nZW5kZXIsIHN1bW1hcnkgPSBGLCByZV9mb3JtdWxhID0gTkEpICU+JSANCiAgYXNfdGliYmxlKCkgJT4lIA0KICByZW5hbWUoSHVuZ3J5X1dvbWVuID0gVjEsIEh1bmdyeV9NZW4gPSBWMiwgU2F0aWF0ZWRfV29tZW4gPSBWMywgU2F0aWF0ZWRfTWVuID0gVjQpICU+JSANCiAgYmluZF9jb2xzKGJhc2VsaW5lX3BlY2tfcHJlZGljdGlvbnMgJT4lIHNlbGVjdChCYXNlbGluZV9lc3RpbWF0ZSkpICU+JSANCiAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gIkdyb3VwIiwgdmFsdWVzX3RvID0gIlBvc3Rlcmlvcl9lc3RpbWF0ZSIsIGNvbHMgPSAxOjQpICU+JSANCiAgc2VwYXJhdGUoc2VwID0gIl8iLCBjb2wgPSBHcm91cCwgaW50byA9IGMoIlRyZWF0bWVudCIsICJHZW5kZXIiKSkNCiAgDQpjYWxjdWxhdGVfYWxsX3RoZV9kaWZmc18zIDwtDQogIGZpdHRlZChwZWNrX21vZGVsX3RyZWF0bWVudF9nZW5kZXIsIA0KICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlciwgc3VtbWFyeSA9IEYsIHJlX2Zvcm11bGEgPSBOQSkgJT4lIA0KICBhc190aWJibGUoKSAlPiUgDQogIHJlbmFtZShIdW5ncnlfV29tZW4gPSBWMSwgSHVuZ3J5X01lbiA9IFYyLCBTYXRpYXRlZF9Xb21lbiA9IFYzLCBTYXRpYXRlZF9NZW4gPSBWNCkgJT4lIA0KICBtdXRhdGUoV29tZW5faF9zX2RpZmYgPSBIdW5ncnlfV29tZW4gLSBTYXRpYXRlZF9Xb21lbiwNCiAgICAgICAgIE1lbl9oX3NfZGlmZiA9IEh1bmdyeV9NZW4gLSBTYXRpYXRlZF9NZW4sDQogICAgICAgICBkaWZmX2RpZmYgPSBXb21lbl9oX3NfZGlmZiAtIE1lbl9oX3NfZGlmZikgJT4lIA0KICBzZWxlY3QoY29udGFpbnMoImRpZmYiKSkgJT4lDQogIHJlbmFtZShgSC1TICh3b21lbilgID0gV29tZW5faF9zX2RpZmYsDQogICAgICAgICBgSC1TIChtZW4pYCA9IE1lbl9oX3NfZGlmZiwNCiAgICAgICAgIGBJbnRlcmFjdGlvbmAgPSBkaWZmX2RpZmYpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAxOjMsIG5hbWVzX3RvID0gImRpZmZfY29udHJhc3QiLCB2YWx1ZXNfdG8gPSAicG9zdGVyaW9yX2RpZmYiKQ0KDQpncDUgPC0gDQogIGdlbmRlcl90cmVhdG1lbnRfZHJhd3NfMiAlPiUgDQogIGdncGxvdChhZXMoeCA9IEdlbmRlciwgeSA9IFBvc3Rlcmlvcl9lc3RpbWF0ZSkpICsgDQogICAgc3RhdF9zbGFiKGFscGhhID0gMC44LCBzaGFwZSA9IDIxLCBhZXMoZmlsbCA9IFRyZWF0bWVudCkpICsNCiAgc3RhdF9zbGFiKGFlcyh5ID0gQmFzZWxpbmVfZXN0aW1hdGUpLA0KICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIGxpbmV3aWR0aCA9IDAuOCwgc2xhYl9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIikgKw0KICAjc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC42NiwgMC45NSksIGFscGhhID0gMC45LA0KICAgIyAgICAgICAgICAgIHBvaW50X2ludGVydmFsID0gIm1lZGlhbl9xaSIsIHBvaW50X2ZpbGwgPSAid2hpdGUiLA0KICAgIyAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSA0LCBzdHJva2UgPSAxLjUsDQogICAjICAgICAgICAgICAgZmlsbCA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIsIDUpWzJdKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMobWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMTApWzRdLCBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAxMClbNl0pKSArDQogIGNvb3JkX2ZsaXAoKSsjeWxpbSA9IGMoMjUsIDU1KSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygsIDAsIDEpKSArDQogIGxhYnMoeCA9ICJHZW5kZXIiLCB5ID0gIkVzdGltYXRlZCBwZWNrcyBwZXIgbWluIiwgZmlsbCA9ICJBbGxvY2F0ZWRcblByaW1lciIpICsNCiAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KDQoNCg0KZ3A2IDwtDQogIGNhbGN1bGF0ZV9hbGxfdGhlX2RpZmZzXzMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkaWZmX2NvbnRyYXN0LCB5ID0gcG9zdGVyaW9yX2RpZmYpKSArIA0KICAgICNzdGF0X3NsYWIoYWxwaGEgPSAwLjksIHNoYXBlID0gMjEsIGFlcyhmaWxsID0gR2VuZGVyKSkgKw0KICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAwLjksDQogICAgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIHBvaW50X3NpemUgPSAzLCBzdHJva2UgPSAxLjUsDQogICAgICAgICAgICAgICBmaWxsID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMTApWzVdKSArDQogICNzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICBjb29yZF9mbGlwKCkrI3lsaW0gPSBjKDI1LCA1NSkpICsNCiAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgbGluZXdpZHRoID0gMC43NSkgKw0KICAjZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xMCwgMTUpKSArDQogIHhsYWIoIkRpZmZlcmVuY2UgY29udHJhc3QiKSArDQogIHlsYWIoIlBlY2tzIHBlciBtaW4iKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpDQoNCg0KIyBleHBlY3RhdGlvbiBtb2RlbA0KDQpnZW5kZXJfZXhwZWN0YXRpb25fZHJhd3NfMiA8LQ0KICBmaXR0ZWQocGVja19tb2RlbF9leHBlY3RhdGlvbl9nZW5kZXIsIA0KICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlcl8yLCBzdW1tYXJ5ID0gRiwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogIGFzX3RpYmJsZSgpICU+JSANCiAgcmVuYW1lKEh1bmdyeV9Xb21lbiA9IFYxLCBIdW5ncnlfTWVuID0gVjIsIFNhdGlhdGVkX1dvbWVuID0gVjMsIFNhdGlhdGVkX01lbiA9IFY0KSAlPiUgDQogIGJpbmRfY29scyhiYXNlbGluZV9wZWNrX3ByZWRpY3Rpb25zICU+JSBzZWxlY3QoQmFzZWxpbmVfZXN0aW1hdGUpKSAlPiUgDQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJHcm91cCIsIHZhbHVlc190byA9ICJQb3N0ZXJpb3JfZXN0aW1hdGUiLCBjb2xzID0gMTo0KSAlPiUgDQogIHNlcGFyYXRlKHNlcCA9ICJfIiwgY29sID0gR3JvdXAsIGludG8gPSBjKCJUcmVhdG1lbnQiLCAiR2VuZGVyIikpDQogIA0KY2FsY3VsYXRlX2FsbF90aGVfZGlmZnNfNCA8LQ0KICBmaXR0ZWQocGVja19tb2RlbF9leHBlY3RhdGlvbl9nZW5kZXIsIA0KICAgICAgICAgbmV3ZGF0YSA9IG5ld19kYXRhX2dlbmRlcl8yLCBzdW1tYXJ5ID0gRiwgcmVfZm9ybXVsYSA9IE5BKSAlPiUgDQogIGFzX3RpYmJsZSgpICU+JSANCiAgcmVuYW1lKEh1bmdyeV9Xb21lbiA9IFYxLCBIdW5ncnlfTWVuID0gVjIsIFNhdGlhdGVkX1dvbWVuID0gVjMsIFNhdGlhdGVkX01lbiA9IFY0KSAlPiUgDQogIG11dGF0ZShXb21lbl9oX3NfZGlmZiA9IEh1bmdyeV9Xb21lbiAtIFNhdGlhdGVkX1dvbWVuLA0KICAgICAgICAgTWVuX2hfc19kaWZmID0gSHVuZ3J5X01lbiAtIFNhdGlhdGVkX01lbiwNCiAgICAgICAgIGRpZmZfZGlmZiA9IFdvbWVuX2hfc19kaWZmIC0gTWVuX2hfc19kaWZmKSAlPiUgDQogIHNlbGVjdChjb250YWlucygiZGlmZiIpKSAlPiUNCiAgcmVuYW1lKGBILVMgKHdvbWVuKWAgPSBXb21lbl9oX3NfZGlmZiwNCiAgICAgICAgIGBILVMgKG1lbilgID0gTWVuX2hfc19kaWZmLA0KICAgICAgICAgYEludGVyYWN0aW9uYCA9IGRpZmZfZGlmZikgJT4lIA0KICBwaXZvdF9sb25nZXIoY29scyA9IDE6MywgbmFtZXNfdG8gPSAiZGlmZl9jb250cmFzdCIsIHZhbHVlc190byA9ICJwb3N0ZXJpb3JfZGlmZiIpDQoNCmdwNyA8LSANCiAgZ2VuZGVyX2V4cGVjdGF0aW9uX2RyYXdzXzIgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBQb3N0ZXJpb3JfZXN0aW1hdGUpKSArIA0KICAgIHN0YXRfc2xhYihhbHBoYSA9IDAuOSwgc2hhcGUgPSAyMSwgYWVzKGZpbGwgPSBUcmVhdG1lbnQpKSArDQogIHN0YXRfc2xhYihhZXMoeSA9IEJhc2VsaW5lX2VzdGltYXRlKSwNCiAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCBsaW5ld2lkdGggPSAwLjgsIHNsYWJfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsNCiAgI3N0YXRfaGFsZmV5ZSgud2lkdGggPSBjKDAuNjYsIDAuOTUpLCBhbHBoYSA9IDAuOSwNCiAgICMgICAgICAgICAgICBwb2ludF9pbnRlcnZhbCA9ICJtZWRpYW5fcWkiLCBwb2ludF9maWxsID0gIndoaXRlIiwNCiAgICMgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gNCwgc3Ryb2tlID0gMS41LA0KICAgIyAgICAgICAgICAgIGZpbGwgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCA1KVsyXSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJIaXJvc2hpZ2UiLCAyKSkgKw0KICBjb29yZF9mbGlwKCkrI3lsaW0gPSBjKDI1LCA1NSkpICsNCiAgI2dlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMikgKw0KICAjc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoLCAwLCAxKSkgKw0KICBsYWJzKHggPSAiR2VuZGVyIiwgeSA9ICJFc3RpbWF0ZWQgcGVja3MgcGVyIG1pbiIsIGZpbGwgPSAiSW5kaWNhdGVkXG5leHBlY3RhdGlvbiIpICsNCiAgdGhlbWVfYncoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkNCg0KDQoNCmdwOCA8LQ0KICBjYWxjdWxhdGVfYWxsX3RoZV9kaWZmc180ICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZGlmZl9jb250cmFzdCwgeSA9IHBvc3Rlcmlvcl9kaWZmKSkgKyANCiAgICAjc3RhdF9zbGFiKGFscGhhID0gMC45LCBzaGFwZSA9IDIxLCBhZXMoZmlsbCA9IEdlbmRlcikpICsNCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC42NiwgMC45NSksIGFscGhhID0gMC45LA0KICAgICAgICAgICAgICAgcG9pbnRfaW50ZXJ2YWwgPSAibWVkaWFuX3FpIiwgcG9pbnRfZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLCBwb2ludF9zaXplID0gMywgc3Ryb2tlID0gMS41LA0KICAgICAgICAgICAgICAgZmlsbCA9IG1ldC5icmV3ZXIoIkhpcm9zaGlnZSIsIDEwKVs1XSkgKw0KICAjc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMikpICsNCiAgY29vcmRfZmxpcCgpKyN5bGltID0gYygyNSwgNTUpKSArDQogICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGxpbmV3aWR0aCA9IDAuNzUpICsNCiAgI2dlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTAsIDE1KSkgKw0KICB4bGFiKCJEaWZmZXJlbmNlIGNvbnRyYXN0IikgKw0KICB5bGFiKCJQZWNrcyBwZXIgbWluIikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQ0KYGBgDQoNCg0KJH4kDQoNCiMjIyBGaW5kIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYmFzZWxpbmUgYW5kIG9ic2VydmVyIGVzdGltYXRlcw0KDQoqKlRhYmxlIFM1KiouIFRoZSBkZWdyZWUgdG8gd2hpY2ggZWFjaCBncm91cCBvZiBvYnNlcnZlcidzIG92ZXJlc3RpbWF0ZXMgZmVlZGluZyByYXRlIChudW1iZXIgb2YgZ3JvdW5kIHBlY2tzIHBlciBtaW51dGUpDQoNCmBgYHtyfQ0KYmFzZWxpbmVfcGVja19wcmVkaWN0aW9ucyAlPiUgc2VsZWN0KEJhc2VsaW5lX2VzdGltYXRlKSAlPiUgIGJpbmRfY29scygNCiAgDQogIGFzX2RyYXdzX2RmKHBlY2tfbW9kZWxfdHJlYXRtZW50KSAlPiUgDQogICAgbXV0YXRlKEh1bmdyeSA9IGV4cChiX0JpYXNfdHJlYXRtZW50SHVuZ3J5KSwNCiAgICAgICAgICAgU2F0aWF0ZWQgPSBleHAoYl9CaWFzX3RyZWF0bWVudFNhdGlhdGVkKSkgJT4lIA0KICAgIHNlbGVjdChIdW5ncnksIFNhdGlhdGVkKSkgJT4lIA0KICBtdXRhdGUoYEJpYXMgdHJlYXRtZW50IFNhdGlhdGVkIC8gQmFzZWxpbmVgID0gU2F0aWF0ZWQgLyBCYXNlbGluZV9lc3RpbWF0ZSwNCiAgICAgICAgIGBCaWFzIHRyZWF0bWVudCBIdW5ncnkgLyBCYXNlbGluZWAgPSBIdW5ncnkgLyBCYXNlbGluZV9lc3RpbWF0ZSkgJT4lIA0KICBzZWxlY3QoY29udGFpbnMoIkJpYXMiKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgdmFsdWVzX3RvID0gImVzdGltYXRlIiwgbmFtZXNfdG8gPSAiU3RhdCIpICU+JSANCiAgZ3JvdXBfYnkoU3RhdCkgJT4lIA0KICBzdW1tYXJpc2VfZHJhd3MoIm1lZGlhbiIsICJzZCIsIH5xdWFudGlsZSgueCwgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksIG5hLnJtID0gVFJVRSksIC5jb3JlcyA9IDQpICU+JSANCiAgc2VsZWN0KC12YXJpYWJsZSkgJT4lIA0KICANCiAgYmluZF9yb3dzKA0KICAgIA0KICAgIGJhc2VsaW5lX3BlY2tfcHJlZGljdGlvbnMgJT4lIHNlbGVjdChCYXNlbGluZV9lc3RpbWF0ZSkgJT4lICBiaW5kX2NvbHMoDQogICAgICANCiAgICAgIGFzX2RyYXdzX2RmKHBlY2tfbW9kZWxfZXhwZWN0YXRpb24pICU+JSANCiAgICAgICAgbXV0YXRlKEh1bmdyeSA9IGV4cChiX0V4cGVjdGF0aW9uSHVuZ3J5KSwNCiAgICAgICAgICAgICAgIFNhdGlhdGVkID0gZXhwKGJfRXhwZWN0YXRpb25TYXRpYXRlZCkpICU+JSANCiAgICAgICAgc2VsZWN0KEh1bmdyeSwgU2F0aWF0ZWQpKSAlPiUgDQogICAgICBtdXRhdGUoYEV4cGVjdGF0aW9uIFNhdGlhdGVkIC8gQmFzZWxpbmVgID0gU2F0aWF0ZWQgLyBCYXNlbGluZV9lc3RpbWF0ZSwNCiAgICAgICAgICAgICBgRXhwZWN0YXRpb24gSHVuZ3J5IC8gQmFzZWxpbmVgID0gSHVuZ3J5IC8gQmFzZWxpbmVfZXN0aW1hdGUpICU+JSANCiAgICAgIHNlbGVjdChjb250YWlucygiRXhwZWN0YXRpb24iKSkgJT4lIA0KICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBldmVyeXRoaW5nKCksIHZhbHVlc190byA9ICJlc3RpbWF0ZSIsIG5hbWVzX3RvID0gIlN0YXQiKSAlPiUgDQogICAgICBncm91cF9ieShTdGF0KSAlPiUgDQogICAgICBzdW1tYXJpc2VfZHJhd3MoIm1lZGlhbiIsICJzZCIsIH5xdWFudGlsZSgueCwgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksIG5hLnJtID0gVFJVRSksIC5jb3JlcyA9IDQpICU+JSANCiAgICAgIHNlbGVjdCgtdmFyaWFibGUpDQogICkgJT4lIA0KICBwYW5kZXIoKQ0KYGBgDQoNCg0KIyBGaWd1cmUgMQ0KDQpPcHRpb24gMQ0KDQpgYGB7ciwgZmlnLmhlaWdodD0xMiwgd2lkdGggPSAxMH0NCihwMiArIHAzKSAvIChwNCArIHA1KSAvIChwNiArIHA3KSAvIChwOCArIHA5KSArDQogICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICdhJykNCmBgYA0KDQpgYGB7ciwgZmlnLmhlaWdodD0xMiwgd2lkdGggPSAxMCwgaW5jbHVkZT1GQUxTRX0NCihncDEgKyBncDIpIC8gKGdwMyArIGdwNCkgLyAoZ3A1ICsgZ3A2KSAvIChncDcgKyBncDgpICsNCiAgIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gJ2EnKQ0KYGBgDQoNCioqRmlndXJlIDEqKi4gUG9zdGVyaW9yIG1lYW4gZXN0aW1hdGVzIGFuZCBkaWZmZXJlbmNlIGNvbnRyYXN0cyBmb3Igb2JzZXJ2ZXIgZXN0aW1hdGVkIGdyb3VwIGZvcmFnaW5nIHBlcmNlbnRhZ2UgYW5kIGluZGl2aWR1YWwgZmVlZGluZyByYXRlcy4gVGhlIGNvbG91cmVkIGFyZWEgaXMgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gYW5kIHRoZSB3aGl0ZSBwb2ludCBpcyB0aGUgbWVhbiBlc3RpbWF0ZSB3aXRoIGFzc29jaWF0ZWQgNjclIGFuZCA5NSUgY3JlZGlibGUgaW50ZXJ2YWxzLiBUaGUgZGlzdHJpYnV0aW9ucyBzaG93biB3aXRoIGRhc2hlZCBsaW5lcyBhcmUgdGhlIHBvc3RlcmlvciBmb3IgYmFzZWxpbmUgcGVjayByYXRlLCBlc3RpbWF0ZWQgZnJvbSBhIHJhbmRvbSBzYW1wbGUgb2YgcGlnZW9ucyBhcHBlYXJpbmcgaW4gdGhlIHZpZGVvLg0KDQoNCiMgU2Vzc2lvbiBpbmZvDQoNCmBgYHtyfQ0Kc2Vzc2lvbkluZm8oKSAlPiUgcGFuZGVyDQpgYGANCg0K